在数字系统中,各模块应采取尽量采取寄存输入和寄存输出,主要有以下优点:
1.模块化清晰(特别是寄存输出)
2.提高系统最高工作速率
3.有利于整个系统和单个模块分别进行静态时序分析
输入电路
dina,dinb对应芯片的输入引脚
always @(negedge rst or posedge clk)
if(!rst)
calc<=0;
else
calc<=dina+dinb;
always @(negedge rst or posedge clk)
if(!rst) begin
in_rega<=0;
in_regb<=0;
end
else begin
in_rega<=dina;
in_regb<=dinb;
end
always @(negedge rst or posedge clk)
if(!rst) begin
in_rega<=0;
in_regb<=0;
end
else begin
calc<=in_rega+regb;
end
如果输入信号来自异步时钟域,必须寄存两拍。第一拍将输入信号同步化,同步后的输出可能带来建立/保持时间的冲突,产生亚稳态,需要再寄存一拍,减少亚稳态带来的影响。
如果输入信号来自同一时钟域且需要用到跳变沿,需要寄存一拍,否则时序报告会clock shew > data delay,造成建立/保持时间的冲突。
对于一般模块的输入信号来说,如果信号来自同一时钟域,各模块的输入不需要寄存,只要满足建立时间、保持时间的约束,就可以保证在时钟的上升沿到来时,输入信号已经稳定。
但是,如果模块需要使用输入信号的跳边沿,则需要处理(边沿检测等)。对于异步时钟域,边沿检测,格雷码,异步FIFO,RAM等
总结如下:
1.全局时钟的跳变沿最可靠。
2.来自异步时钟域的输入需要寄存一次以同步化,再寄存一次以减少亚稳态带来的影响。
3.不需要用到跳变沿的来自同一时钟域的输入,没有必要对信号进行寄存。
4.需要用到跳变沿的来自同一时钟域的输入,寄存一次即可。
5.需要用到跳变沿的来自不同时钟域的输入,需要用到3个触发器,前两个用以同步,第3个触发器的输出和第2个的输出经过逻辑门来判断跳变沿。
always @ (posedge Clk) //不对输入信号进行寄存
begin
if (inputs)
begin
...
end
...
end
always @ (posedge Clk) //对输入信号寄存一拍
begin
inputs_reg <= inputs;
if (inputs_reg == 1'b0 && inputs == 1'b1)
begin
...
end
...
end
always @ (posedge Clk) //对输入信号寄存三拍
begin
inputs_reg1 <= inputs;
inputs_reg2 <= inputs_reg1;
inputs_reg3 <= inputs_reg2;
if (inputs_reg2 == 1'b1 && inputs_reg3 == 1'b0)
begin
...
end
...
end
输出电路
tempa tempb为管脚输出信号
always @(tempa or tempb)
case(tempa)
0:dout<=tempb+1;
1:dout<=tempb+3;
......
default:dout<=0;
endcase
always @(negedge rst or posedge clk)
if(!rst)
dout<=0;
else
case(tempa)
0:dout<=tempb+1;
1:dout<=tempb+3;
......
default:dout<=0;
endcase