September 14, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52540819
声明:转载请注明作者及出处。
时序逻辑中为了响应不同的状态,需要对信号进行记忆。存储信号的电路常用的有锁存器(Latches)和D触发器(D-type Flip-Flop),前者使用时钟电平捕获信号,后者使用时钟沿捕获信号。对于使用时钟沿捕获数据的电路结构,同步系统中用Register表示,中文译为寄存器。因此,D触发器是寄存器的一种。
在下面的例子中,用Verilog进行一个D-Latch的RTL的建模示例和一个寄存器(D flip-Flop)的RTL建模示例。最后描绘一个计数器。
锁存器(D-Latch)的RTL的建模
module d_latch(d,clk,q);
input d;
input clk;
output q;
reg q;
always @ (d,clk)
if(clk)
q <= d;
endmodule
`timescale 1ns / 1ns
module d_latch_tb;
reg clk,d;
wire q;
d_latch u1(.d(d),.clk(clk),.q(q));
initial
begin
clk = 1;
d <= 0;
forever
begin
#60 d <= 1;//人为生成毛刺
#22 d <= 0;
#2 d <= 1;
#2 d <= 0;
#16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
end
end
always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule
在它的Testbench中,其中特别设计了一段毛刺,当clk为高时,d信号被捕获,但同时d信号的变化也反映在输出q中,电平敏感锁存器的透明性质,使得组合电路的毛刺(glitches)被输出,导致一些问题。因此一些FPGA手册强调对锁存器的慎用。(类似于软件编程里慎用goto语句)
D型触发器(D flip-Flop)的RTL建模
上图中的小三角代表沿敏感
module d_flip_flop(d,clk,q);
input d;
input clk;
output q;
reg q;
always @ (posedge clk)//我们用正的时钟沿做它的敏感信号
begin
q <= d;//上升沿有效的时候,把d捕获到q
end
endmodule
`timescale 1ns / 1ns
module d_flip_flop_tb;
reg clk,d;
wire q;
d_flip_flop u1(.d(d),.clk(clk),.q(q));
initial
begin
clk = 1;
d <= 0;
forever
begin
#60 d <= 1;//人为生成毛刺
#22 d <= 0;
#2 d <= 1;
#2 d <= 0;
#16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
end
end
always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule
加入复位信号之后:
module d_flip_flop_rst(clk,d,rst,q);
input d;
input clk;
input rst;
output q;
reg q;//上电以后,在时钟没有工作之前,这个寄存器应该是个什么信号呢,就是初始化的信号
//通常上电初始化我们用复位信号来做,用复位信号来指定复位以后的状态
// always @ (posedge clk)//我们用正的时钟沿做它的敏感信号
// begin
// if(rst)//同步复位信号
// q <=0;
// else
// q <= d;//上升沿有效的时候,把d捕获到q
// end
always @ (posedge clk,posedge rst)//我们用正的时钟沿做它的敏感信号
begin
if(rst)//异步复位信号,跟时钟沿无关,只要复位是高电平就会复位
q <=0;
else
q <= d;//上升沿有效的时候,把d捕获到q
end
endmodule
32位计数器
插入图片
module counter(clk,reset,q);
input clk;
input reset;
output [31:0] q;
reg [31:0] q;//上电以后,在时钟没有工作之前,这个寄存器应该是个什么信号呢,就是初始化的信号
//通常上电初始化我们用复位信号来做,用复位信号来指定复位以后的状态
always @ (posedge clk)//在同步复位的情况下,不需要把复位信号放到敏感表里面
begin
if(reset)//复位高电平的时候做初始化
q <= 32'h0000_0000;
else//复位结束以后让它捕获信号
q <= q + 1;
end
endmodule
来源:
https://ke.qq.com/user/tasks/index.html?cid=117307#tid=100127911&fr=2