一、FPGA学习笔记(一)入门背景、软件及时钟约束
二、FPGA学习笔记(二)Verilog语法初步学习(语法篇1)
三、FPGA学习笔记(三) 流水灯入门FPGA设计流程
四、FPGA学习笔记(四)通过数码管学习顶层模块和例化的编写
五、FPGA学习笔记(五)Testbench(测试平台)文件编写进行Modelsim仿真
六、FPGA学习笔记(六)Modelsim单独仿真和Quartus联合仿真
七、FPGA学习笔记(七)verilog的深入学习之任务与函数(语法篇3)
在学习FPGA串口通信的过程中,遇到了串口接收中打拍处理的问题,有的人打两拍,有的打三拍,于是决定分析一下到底打几拍才是最好的。
提示:以下是本篇文章正文内容,下面案例可供参考
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_rx_d1 <= 1'b0;
uart_rx_d2 <= 1'b0;
uart_rx_d3 <= 1'b0;
end
else begin
uart_rx_d1 <= uart_rxd;
uart_rx_d2 <= uart_rx_d1;
uart_rx_d3 <= uart_rx_d2;
end
end
如程序中所写,打拍就是把信号进行记录保存,同时带有一定延后性。
uart_rx_d1 这里存放的最新的数据
uart_rx_d2 存放的是前一个数据
uart_rx_d3 存放的上上一个数据
同时这里使用的是非阻塞赋值,所以这几个值只能赋值后的下一个周期才能判断。
要注意的是这里的打拍只能从慢时钟域到快时钟域才能实现。
首先是因为可能出现亚稳态的现象,其次是为了判断上升沿和下降沿。
亚稳态现象:
当时钟信号上升沿到来的时候正好采样的数据也在发生变化,但是如果想要采样得到一个稳定值,在clk的上升沿的前一段时间有一个建立时间TSU和在clk的上升沿的后一段时间有一个保持时间Th,如果在这两个时间段内采样的信号发生跳变的话,输出的信号就会出现0,1之间跳变的不稳定、不确定状态。
1.全局时钟的跳变沿最可靠。
2.来自异步时钟域的输入需要寄存一次以同步化,再寄存一次以减少亚稳态带来的影响。
3.不需要用到跳变沿的来自同一时钟域的输入,没有必要对信号进行寄存。
4.需要用到跳变沿的来自同一时钟域的输入,寄存一次即可。
5.需要用到跳变沿的来自不同时钟域的输入,需要用到3个触发器,前两个用以同步,第3个触发器的输出和第2个的输出经过逻辑门来判断跳变沿。
一般复位采用的是异步复位:
always @ (posedge clk or negedge rst_n) begin
if (!rst_n)
xxxx;
else if (xx) begin
xxxx;
xxxx;
end
end
这里收到复位的下降沿就程序执行,但是当由低到高释放时,应该会出现亚稳态。
always @ (posedge clk) begin
if (!rst_n)
xxxx;
end
即如果复位信号有效,则只能在时钟上升沿让电路复位。同样有亚稳态的现象的可能性。
异步复位,同步释放(复位信号):在rst_n信号为低时,立刻进行复位,而rst_n信号由低到高释放时,为了防止亚稳态的出现,将rst_n信号用DFF向后延一周期,达到与时钟clk边沿同步的目的。
input clk ;
input rst_n ;
output reg rst_s2;
reg rst_s1;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rst_s1 <= 1'b0;
rst_s2 <= 1'b0;
end
else begin
rst_s1 <= 1'b1 ;
rst_s2 <= rst_s1 ;
end
end
常见的串口接收时,寄存三次:(一般一个时钟周期内,亚稳态会稳定)
如上图所示,一般用reg2和reg3来判断上升沿/下降沿,这就是寄存三次的时序图,但是看这个图,好像reg3没有必要,因为亚稳态一个周期内稳定后,是可以用reg2和reg1判断上下升降沿
第一级寄存器产生亚稳态并经过自身后可以稳定输出的概率为 70%~80%左右,第二级寄存器可以稳定输出的概率为 99%左右。
所以一般第二级的寄存器自身肯定能稳定,图上就是第一级没有稳定,第二级稳定了,然后再加一级就可以判断上升沿和下降沿。
所以打几拍就要看信号的可靠性了,这里有些问题,D触发器不是在时钟信号上升沿到来后才有信号输出吗,那么这一周期不应该是亚稳态状态吗?
最后查阅资料发现自己对亚稳态不熟悉:亚稳态并不会一直持续,也就是说,D触发器在亚稳态期间会0-1波动,但之后会慢慢稳定下来,就像上面的图,最后是一个确定值,所以这也就是为什么要加多级寄存器,目的是让亚稳态过渡过去。(一开始以为D触发器只会在时钟上升沿的时候输出信号,所以一遇到亚稳态就一整个周期都信号不确定了,所以不明白为什么会有第二级寄存器采集到是一个确定值,原来慢慢会自己稳定)