锁存器
锁存器是电平触发存储单元(一种具有记忆功能的逻辑器件),数据存储动作需要高低电平信号使能,才可以保存当前状态。
但是锁存器要尽量避免使用,它会影响下一级电路,而且不能过滤信号毛刺。所以,一般能用触发器的地方,是不会用锁存器的。
在Verilog里面,一个存储器表示为:
module mux(
input a,
input b,
output reg y // output signal
);
always @ (*) begin
case ( a )
1 : y = b ;
default : y = 0 ;
endcase
end
endmodule
上述在always没有触发条件,只要输入a变成高电平即可把数据记忆在y里面。如果某一瞬间信号出现了尖峰毛刺,误判高电平,直接导致后续系统出错。
触发器
也是一种具有记忆功能的逻辑单元(判断电平是否跳变,然后在保存当前状态),但是需要电平跳变瞬间触发。触发器一般接有时钟信号,用于触发后续电路动作,有一定的信号毛刺过滤功能。所以,触发器一般比锁存器应用更加广泛。
在Verilog里面,已经成为了一种通用的语法被广发使用,例如以下语句:
always @(posedge sys_clk or negedge sys_rst_n) begin
......
end
这一句本质就是一个触发器,当时钟上升沿出现才会触发后续电路工作。
寄存器
寄存器需要多个触发器串联组成,如下图结构所示:
当地一个时钟节拍到达时候,保存第一位数据。第二个时钟节拍到达的时候,第一位数据往后一级触发器移动,新一位数据进入,如此类推。
在Verilog里面可以这样实现:
module shift_reg (
input clk , // system clock 50Mhz on board
input rst_n, // system rst, low active
input a ,
output y // output signal
);
always @ (posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
a_dly1 <= 1'b0 ;
a_dly2 <= 1'b0 ;
a_dly3 <= 1'b0 ;
a_dly4 <= 1'b0 ;
end
else begin
a_dly1 <= a ;
a_dly2 <= a_dly1 ;
a_dly3 <= a_dly2 ;
a_dly4 <= a_dly3 ;
end
end
assign y = a_dly4 ;
endmodule
计数器
一种可以统计输入信号个数的记数器,可以实现精确的延时,或者时钟分频。在电路设计中广泛使用,例如下面一个3bit的计数器:
在Verilog里面一般这样表达:
module CNT (
input clk , // system clock 50Mhz on board
input rst_n, // system rst, low active
output reg [2:0] y // output signal
);
always @ (posedge clk or negedge rst_n) begin
if (rst_n == 1'b0)
y <= 3'b0 ;
else
y <= y + 1'b1 ;//当寄存器溢出就清零
end
endmodule