将来自于不同设计组件的电路合在一起,组成一个更高级的电路。
根据所调用子模块的不同抽象级别,可以将模块的结构描述方式分成如下三类:
- 模块级建模:调用用户设计生成的低级子模块对硬件电路结构进行说明。模块由低级模块的实例组成
- 门级建模:调用Verilog内部的基本门级元件对硬件电路结构进行说明。模块由基本门级元件的实例组成
- 开关级建模:调用Verilog内部的基本开关元件对硬件电路的结构进行说明。模块由基本开关级元件的实例组成(Verilog区别于VHDL的重要特点)
模块级建模
模块调用方式
module and_2(a,b,c); //2输入与门模块
input a,b;
output c;
assign c=a&b;
endmodule
module logic(in1,in2,q); //顶层模块
input in1,in2;
output q;
and_2 U1(in1,in2,q); //模块的调用,U1是实例名,将and_2实例化
endmodule
当需要对同一个模块进行多次调用时,可以采用阵列调用方式:
<被调用模块名><实例阵列名>[阵列左边界:阵列有边界](<端口连接表>);
module AND(andout ina inb);
input ina,inb;
output andout;
assign andout=ina&inb;
endmodule
module ex_array(out,a,b);
input[15:0] a,b;
output[15:0] out;
wire[15:0] out;
AND AND_ARREY[15:0](out,a,b); //AND模块调用
endmodule
其中阵列模块调用语句相当于:
AND AND_ARRAY15(out[15],a[15],b[15]);
AND AND_ARRAY14(out[14],a[14],b[14]);
...
AND AND_ARRAY1(out[1],a[1],b[1]);
AND AND_ARRAY0(out[0],a[0],b[0]);
也可使用连续赋值语句:
assign out=a&b
模块端口对应方式
端口位置对应
如上例都是。
例:半加器,输出两个信号:和与进位。其中和信号即为输入值做异或,进位即为输入值做与。
module halfadder(a,b,s,c);
input a,b;
output s,c;
assign s=a^b;
assign c=a&b
endmodule
两个半加器构成一个全加器:
module fulladder(p,q,ci,co,sum)
input p,q,ci;
output co,sum;
wire w1,w2,w3;
halfadder U1(p,q,w1,w2);
halfadder U2(ci,w1,sum,w3);
or U3(co,w2,w3)
endmodule
端口名称对应
模块名<参数值列表>实例名(端口名1<信号名1>,端口名2<信号名2>,...,端口名n<信号名n>);
例:
module dff(d,clk,clr,q); //D触发器模块
input d,clk,clr;
output q;
reg q;
always@(posedge clk or negedge clr)
begin
if(!clr)
q=0;
else
q=d;
end
endmodule
module shifter_D(din,clock,clear,out);
input din,clock,clear;
output[3:0] out;
dff U1(q(out[0]),d(din),clk(clock),clr(clear));
dff U1(q(out[1]),d(out[0]),clk(clock),clr(clear));
dff U1(q(out[2]),d(out[1]),clk(clock),clr(clear));
dff U1(q(out[3]),d(out[2]),clk(clock),clr(clear));
不同端口位宽的匹配
错误命题,但在语法结构中,有解决方式:
module ex1(a,b);
input[6:1] a;
output[3:0] b;
endmodule
module test;
wire[5:3] c;
wire[5:1] d;
ex1 U1(a(c),b(d));
endmodule
模块参数值
用以下两种途径改变模块实例参数值:
- 使用带有参数的模块实例语句修改参数值
模块实例本身就能指定新的参数值:
模块名<参数值列表>调用名(端口名列表);
例:
module para1(C,D)
parameter a=1
parameter b=1;
endmodule
module para2:
para1 #(4,3) U1(C1,D1); //位置对应
para1 #(b(6),a(5)) U2(C2,D2); //名称对应
- 使用定义参数语句(defparam语句)修改参数值
在进行模块调用时更改被调用模块内参数值的第二种方式就是利用参数重定义语句(defparam语句)
语法格式:
defparam 参数名1=参数值1,
参数名2=参数值2,
...
参数名n=参数值n;
例:
module halfadder(a,b,s,c)
halfadder
input a,b;
output c,s;
parameter xor_delay=2,and_delay=3;
assign #xor_delay s=a^b;
assign #and_delay c=a&b;
endmodule
module fulladder(p,q,ci,co,sum);
fulladder
input p,q,ci;
output co,sum;
parameter or_delay=1;
wire w1,w2,w3;
halfadder U1(p,q,w1,w2);
halfadder U2(ci,w1,sum,w3);
or #or_delay U3(co,w2,w3);
endmodule
module top1(top1a,top1b,top1s,top1c);
//修改半加器模块参数的模块top1
input top1a,top1b;
output top1s,top1c;
defparam U1.xor_delay=4;
U1.and_delay=5;
//名为U1的半加器实例中对参数xor_delay和参数and_delay的修改
halfadder U1(top1a,top1b,top1s,top1c);
endmodule
module top2(top2p,top2q,top2ci,top2co,top2sum);
input top2p,top2q,top2ci;
output top2co,top2sum;
defparam U2.U1.xor_delay=6,
U2.U2.and_delay=7,//名为U2的全加器实例中引用的名为U2的半加器实例中对参数xor_delay和and_delay的修改
U2.or_delay=5;//名为U2的全加器实例中对参数or_delay值的修改
fulladder U2(top2p,top2q,top2ci,top2co,top2sum);
endmodule
门级建模
多输入门元件调用:
and A1(out1,in1,in2);
or O2(a,b,c,d);
xor X1(x_out,p1,p2); //先列输出端口,再列输入端口
多输出门元件调用:
not NOT_1(out1,out2,in);
buf BUF_1(bufout1,bufout2,bufout3,bufin); //先列输出端口,再列输入端口
三态门元件调用的语法格式:
bufif1 BF1(data_bus,mem_data,enable); //输出端口,输入端口,控制输入端口
bufif0 BF0(a,b,c)
输入输出引脚个数都不能超过10。
开关级建模
nmos开关电路:
module aNMOS(din,ctr,out);
input din,ctr;
output out;
nmos U1(out,din,ctr); //调用nmos开关
endmodule
当ctr为高电平时导通,输入din传到输出端out,当ctr为低电平时,输入输出断开。