`timescale 1 ns/ 1 ns
module _2Divider (Q,CP,Rd_);
output reg Q;
input CP,Rd_;
wire D;
assign D = ~Q;
always @(posedge CP or
negedge Rd_)
if(~Rd_) Q <= 1'b0;
else Q <= D;
endmodule
复制代码
(2)激励块:给输入变量赋值。
`timescale 1 ns/ 1 ns
module test_2Divider();
reg CP, Rd_; wire Q;
//调用(例化)设计块
_2Divider U1 ( .CP(CP), .Q(Q),.Rd_(Rd_) );
initial begin //产生复位信号Rd_
Rd_ = 1'b0;
Rd_ = #2000 1'b1;
#8000 $stop;
end
always begin //产生时钟信号CP
CP = 1'b0;
CP = #500 1'b1;
#500;
end
endmodule
复制代码
(3)仿真波形(用ModelSim)
由图可知,时钟CP的周期为1000ns,在2000ns之前,清零信号Rd_有效,输出Q被清零。在此之后,Rd_=1,在2500ns时,CP上升沿到来,Q=1;到下一个CP上升沿(3500ns)时,Q=0,再到下一个CP上升沿(4500ns)时,Q=1,……,如此重复,直到8000ns时,系统任务$stop被执行,仿真停止。
总之,在不考虑清零信号Rd_的作用时,每当CP上升沿到来时,触发器状态Q翻转一次。输出信号Q的频率正好是CP频率的二分之一,故称该电路为2分频电路。所谓分频电路,是指可将输入的高频信号变为低频信号输出的电路。
例5 试对图所示电路进行建模,并给出仿真结果。
4位异步二进制计数器逻辑图
解:(1)设计块:采用结构描述风格的代码如下。编写了两个模块,这两个模块可以放在一个文件中,文件名为Ripplecounter.v。
第一个主模块Ripplecounter作为设计的顶层,它实例引用分频器子模块_2Divider1共4次,第二个分频器子模块_2Divider1作为设计的底层。
`timescale 1 ns/ 1 ns
/*==== 设计块:Ripplecounter.v ====*/
module Ripplecounter (Q,CP,CLR_);
output [3:0] Q;
input CP, CLR_;
//实例引用分频器模块 _2Divider1
_2Divider1 FF0 (Q[0],CP ,CLR_);
//注意, 引用时端口的排列顺序--位置关联
_2Divider1 FF1 (Q[1],~Q[0],CLR_);
_2Divider1 FF2 (Q[2],~Q[1],CLR_);
_2Divider1 FF3 (Q[3],~Q[2],CLR_);
endmodule
复制代码
设计的底层模块 _2Divider1
//分频器子模块
module _2Divider1 (Q,CP,Rd_);
output reg Q;
input CP,Rd_;
always @(posedge CP or negedge Rd_)
if(!Rd_)
Q <= 1'b0;
else
Q <= ~Q;
endmodule
复制代码
(2)激励块:给输入变量(CLR_和CP)赋值。
/*==== 激励块:test_Ripplecounter.v ====*/
module test_Ripplecounter();
reg CLR_, CP;
wire [3:0] Q;
Ripplecounter i1 (.CLR_(CLR_),.CP(CP),.Q(Q));
initial begin // CLR_
CLR_ = 1'b0;
CLR_ = #20 1'b1;
#400 $stop;
end
always begin // CP
CP = 1'b0;
CP = #10 1'b1;
#10;
end
endmodule
复制代码
(3)仿真波形:如下图所示。
由图可知,
- 时钟CP的周期为20ns。
- 开始时,清零信号CLR_有效(0~20ns),输出Q被清零。
- 20ns之后,CLR_一直为高电平,
- 在30ns时,CP上升沿到来, Q=0001;到下一个CP上升沿(50ns)时,Q=0010,
- 再到下一个CP上升沿(70ns)时,Q=0011,……,如此重复,到310ns时,Q=1111,
- 到330ns时,Q=0000,……,直到系统任务$stop被执行,仿真停止。