前言:
本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。
目录如下:
1.数字IC手撕代码-分频器(任意偶数分频)
2.数字IC手撕代码-分频器(任意奇数分频)
3.数字IC手撕代码-分频器(任意小数分频)
4.数字IC手撕代码-异步复位同步释放
5.数字IC手撕代码-边沿检测(上升沿、下降沿、双边沿)
6.数字IC手撕代码-序列检测(状态机写法)
7.数字IC手撕代码-序列检测(移位寄存器写法)
8.数字IC手撕代码-半加器、全加器
9.数字IC手撕代码-串转并、并转串
10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)
11.数字IC手撕代码-有限状态机FSM-饮料机
12.数字IC手撕代码-握手信号(READY-VALID)
13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)
14.数字IC手撕代码-泰凌微笔试真题
15.数字IC手撕代码-平头哥技术终面手撕真题
16.数字IC手撕代码-兆易创新笔试真题
17.数字IC手撕代码-乐鑫科技笔试真题(4倍频)
18.数字IC手撕代码-双端口RAM(dual-port-RAM)
...持续更新
为了方便可以收藏导览博客: 数字IC手撕代码-导览目录
目录
异步复位同步释放
代码
testbench
波形
异步复位同步释放
请你用verilog,设计一个电路实现异步复位同步释放功能。
为什么要,异步复位同步释放?这个功能有什么用?
这八个字包含两个步骤,异步复位,同步释放
异步复位的意思是复位信号rstn和clk信号不是同时到来的,在always语句块中表现为:
always @(posedge clk or negedge rstn) begin
if(!rstn)
reg _1 <= 1'b0;
end
当异步复位信号到来时,寄存器 reg_1 会被直接拉低,这是不会产生问题的,当rstn下降沿和clk上升沿同时到来时,如果rstn比clk先到来一瞬间,且原来的reg_1信号为1,reg_1会被拉低为0,后一瞬间,clk来了,因为前一瞬间的reg_1值被拉低了,所以在clk到来时,一定有set_up不满足要求...
但是,一进always 语句块后,由于rstn是0,所以reg_1会被赋值为0,还是0。也就是说不管我reg_1的set_up / hold满不满足要求,reg_1都会被重置到0,不会有任何问题,如图所示:
综上所述,异步复位信号是不会产生问题的,但是为什么要同步释放?是释放信号会出问题吗?
答:是的,当rstn释放的时候(从0变1)时,如果rstn释放边沿和clk释放边沿很接近,那么就会出现亚稳态,而亚稳态在电路里面是非常致命的,在亚稳态采样到的数据是不准确的,而电路中一个不准确的值,会导致这后面的所有值都不准确。
当rstn释放的时候,寄存器的输入端D可能因为某个组合逻辑电路和rstn有关系,导致D随rstn同步拉高。那在clk上升沿到来的时候,就会有D的set_up不满足,出现亚稳态,边沿采样的时候,输出reg_1不知道该采D=0的信号还是D=1的信号,所以不妨打两拍,不着急在rstn释放的时候采样,用两个寄存器来延迟两个周期,等到数据D稳定了之后再同步拉高rstn采样。
代码
module asyn_rstn_syn_re(
input clk ,
input rstn ,
output reg rstn_out
);
reg rstn_1;
always @(posedge clk or negedge rstn)begin
if(!rstn)begin
rstn_1 <= 1'b0;
rstn_out <= 1'b0;
end
else begin
rstn_1 <= rstn;
rstn_out <= rstn_1;
end
end
endmodule
testbench
module asyn_rstn_syn_re_tb();
reg clk,rstn;
wire rstn_out;
always #10 clk = ~clk;
initial begin
clk <= 1'b0;
rstn <= 1'b0;
#30
rstn <= 1'b1;
end
asyn_rstn_syn_re u_asyn_rstn_syn_re(
.clk (clk) ,
.rstn (rstn) ,
.rstn_out (rstn_out)
);
endmodule
波形
总结:异步复位为0 的时候不做处理,当rstn从0变1的时候,打两拍随clk同步拉高,此时寄存器输入的D已经稳定很长时间,可以避免亚稳态的发生。