verilog-HDL
目录
用户自定义元件
层次化设计方法
模块例化方法
生成语句
用户自定义元件
Verilog HDL定义的基元都具有固定的功能。为了应用方便,Verilog还支持用户自定义原语(User-Defined Primitive,简称UDP),即允许设计者根据需要自己规划所需要的功能电路。
UDP是以真值表/状态表为基础,通过将真值表/状态表描述的逻辑关系映射到存储器中来实现功能电路。
具体的语法格式为:
primitive <UDP名>(输出信号,输入信号,...);<输出/输入信号声明>initial <输出信号=初值>;table<真值表/状态表>;...endtable
endprimitive
应用UDP既可以描述组合逻辑电路,也可以描述时序逻辑电路。用UDP描述组合逻辑电路时,真值表必须按输入/输出的顺序排列。
用UDP描述2选一数据选择器。primitive mux2to1_pr(D0,D1,A0,y);output y;input D0,D1;input A0;table// D1,D0,A0 : y? 0 0 : 0;? 1 0 : 1;0 ? 1 : 0;1 ? 1 : 1;? ? x : x;endtableendprimitive
层次化设计方法
设计者从现有的元件库中选择适合的元器件来设计功能模块,然后由功能模块组成子系统,再由子系统构成更高一级的子系统,逐级向上直到实现整个系统。 从系统顶层开始,把系统分解为功能模块,然后把 每个功能模块再分解为下一层次的模块,用一系列分层次的模块来表示复杂的数字系统,逐层描述设计思想并进行仿真验证,直到可以用元件库中的元器件实现为止。
在复杂数字系统设计过程中,通常是将以上两种设计方法相结合,兼有以上两种方法的优点。在高层系统中用自顶而下的设计方法实现,而使用自底而上的方法从库元件或以往设计库中调用已有的单元电路来设计功能模块。
在EDA设计中,对于系统的顶层设计模块,通常采用结构化描述方式,即在顶层电路分别例化各功能模块,描述模块之间的连接关系。而对于低层模块,可以采用数据流描述或者行为描述方式, 有利于定义和重构模块的功能。
模块例化方法
名称关联方式的语法格式为: .子模块端口 1(实例端口名), …, .子模块端口 n(实例端口名)
位置关联(in-order)方式不需要写出子模块定义时的端口名称,只需要把实例模块的端口名按子模块定义时的端口顺序排放就能自动映射到子模块的对应端口。
`include "full_adder.v" // 文件包含指令module adder4bits (A,B,S,CO);input [3:0] A,B;output [3:0] S;output CO;wire C1,C2,C3;full_adder FA1(.a(A[0]),.b(B[0]),.ci(0), .sum(S[0]),.co(C1));full_adder FA2(.a(A[1]),.b(B[1]),.ci(C1),.sum(S[1]),.co(C2));full_adder FA3(.a(A[2]),.b(B[2]),.ci(C2),.sum(S[2]),.co(C3));full_adder FA4(.a(A[3]),.b(B[3]),.Cci(C3),.sum(S[3]),.co(CO));endmodule
文件包含指令的语法格式为 `include “<被包含的模块文件名>”
使用文件包含指令应注意以下三点: (1) 一条“`include”只能包含一个文件。有多个文件包含时,可以用多条“`include”描述; (2) 被包含模块需要写出完整的文件名信息,包括文件类型名; (3) 如果被包含的文件不在当前工程目录中时,需要指明文件的完整路径,如“c:/intelFPGA/18.1/full_adder.v”。
需要说明的是,当被包含的文件处于当前工程目录中时,文件包含指令的描述实际上是多余的,可以删掉,因为Quartus Prime编译时会自动根据例化语句的表述,在当前工程目录中找到被例化的模块文件。但是,在例2-24代码中添加文件包含语句的好处是,能够使模块之间的相关关系更为清晰。
生成语句
在数字系统设计中,有时需要编写结构相同但参数不同的语句或者模块。当语句或者模块很多时,采用逐行列写的方法既不简洁,而且效率很低。 generate语句配合循环语句、条件语句和分支语句可编写参数化的例化语句、赋值语句或者复制模块等操作,用于生成模块、线网/变量、参数定义语句、连续赋值语句、行为语句、DUP以及任务和函数等语法结构。 generate语句有 generate for、generate if 和 generate case 三种应用形式。
generate for语句用于复制语句或者模块,每次循环生成一个实例。在应用generate for语句时,需要配套使用Verilog-2001标准中新增关键词genvar定义的索引(index)变量。
应用generate for语句的语法格式为genvar 索引变量;generate for (索引变量=初值; 索引变量≤终值;索引变量=索引变量±常数)begin: 块名 // 关键词begin和end,以及块名都不能省略语句;...;endendgenerate
generate if语句将模块的参数作为条件表达式,用来产生满足条件的语法结构。
module bin2gray #(parameter N=8)(input [N-1:0] bin_code,output wire [N-1:0] gray_code);// 根据转换公式描述assign gray_code[N-1] = bin_code[N-1];genvar i;generate for (i=N-2;i>=0; i=i-1 )begin: BIN2GRAYassign gray_code[i] = bin_code[i+1]^bin_code[i];endendgenerate
endmodule
module MUX2to1a (D0,D1,sel,y);input D0,D1;input sel;output y;assign y = sel? D1:D0;
endmodule
module MUX2to1b (D0,D1,sel,y);input D0,D1;input sel;output reg y;always @(D0,D1,sel)case (sel)0: y = D0;1: y = D1;default: y = D0; endcase
endmodule
generate_case语句与generate_if语句的功能相同,根据模块的参数作为判断条件,用来生成满足条件的语法结构。
// 例化选择
module MUX2to1_tst (D0,D1,sel,y);input D0,D1;input sel;output y;parameter MUX_CASE=1; // 设置为行为描述generate // 分支生成case ( MUX_CASE ) // synopsys full_case0: MUX2to1a U_MUX2to1a (.D0(D0), .D1(D1),.sel(sel),.y(y));1: MUX2to1b U_MUX2to1b (.D0(D0), .D1(D1),.sel(sel),.y(y));endcaseendgenerate
endmodule