1、FIFO(First In First Out,先进先出)
内存数组定义reg [DATA_WIDTH - 1 : 0] fifo_buffer [DATA_DEPTH - 1 : 0];
同步FIFO模块:写控制逻辑、读控制逻辑、计数器(读-1,写+1)、满信号、空信号
异步FIFO模块:写控制逻辑、读控制逻辑、格雷码转换、格雷码同步、满信号、空信号
拓展:将空将满、位宽转换
作用:数据缓存(多bit跨时钟域、位宽转换)
学到的知识:
跨时钟域处理[1-4]:
(1)单bit慢时钟到快时钟:双级触发器缓存法,俗称延迟打拍法。异步信号从一个时钟域进入另一个时钟域之前,将该信号用两级触发器连续缓存两次,可有效降低因为时序不满足而导致的亚稳态问题;
部分Verilog:
reg [1:0] sig2_r ; //2级缓存用于同步
always @(posedge clk_fast or negedge rstn) begin
if (rstn == 1’b0)
sig2_r <= 3'b0 ;
else
sig2_r <= {sig2_r[0], sig1} ; //缓存sig1
end
(2)单bit快时钟到慢时钟:可按电平信号和脉冲信号来区分。
电平信号同步:同步逻辑设计中,电平信号是指长时间保持不变的信号。保持不变的时间限定是相对于慢时钟而言的。只要快时钟的信号保持高电平或低电平的时间足够长,以至于能被慢时钟在满足时序约束的条件下采集到,就可以认为该信号为电平信号。
既然电平信号能够被安全的采集到,所以从快时钟域到慢时钟域的电平信号也采用延迟打拍的方法做同步。
脉冲信号同步:采用"快时钟域脉宽扩展(保证快时钟信号宽度满足超过慢时钟的时钟周期1.5倍,通常的做法是:发送一个使能控制信号,将它同步到新的时钟域,然后通过另一个同步器将同步信号作为确认信号传回发送时钟域再拉低)+慢时钟域延迟打拍"的方法。
如果有时窄脉冲信号又表现出电平信号的特点,即有时信号的有效宽度大于慢时钟周期而能被慢时钟采集到,那么对此类信号再进行脉冲扩展显然是不经济的。此时,可通过"握手传输"的方法进行同步。缺点是:在允许控制信号改变之前,在两个方向上同步控制信号可能会有相当大的延迟。也就是说,在应答信号(pulse_slow2f_r[1])到来之前,是不允许源信号改变的(pulse_slow2f_r[1] = 0时,pulse_fast_r始终为高电平;pulse_slow2f_r[1] = 1时,pulse_fast_r = pulse_fast)。
假设脉冲信号的高电平期间为有效信号期间,其基本原理如下。
(1) 快时钟域对脉冲信号进行检测,检测为高电平时输出高电平信号 pulse_fast_r。或者快时钟域输出高电平信号时,不要急于将信号拉低,先保持输出信号为高电平状态。
(2) 慢时钟域对快时钟域的信号 pulse_fast_r 进行延迟打拍采样。因为此时的脉冲信号被快时钟域保持拉高状态,延迟打拍肯定会采集到该信号。
(3) 慢时钟域确认采样得到高电平信号 pulse_fast2s_r 后,再反馈给快时钟域。
(4) 快时钟域对反馈信号 pulse_fast2s_r 进行延迟打拍采样。如果检测到反馈信号为高电平,证明慢时钟域已经接收到有效的高电平信号。如果此时快时钟域自身逻辑不再要求脉冲信号为高电平状态,拉低快时钟域的脉冲信号即可。
此方法实质是通过相互握手的方式对窄脉冲信号进行脉宽扩展。(造成了脉冲持续时间信号变化丢失,如果不想丢失使用1bit异步FIFO)
部分Verilog:
//(1) 快时钟域检测到脉冲信号时,不急于将脉冲信号拉低
always@(posedge clk_fast or negedge rstn) begin
if (!rstn)
pulse_fast_r <= PULSE_INIT ;
else if (!clear_n)
pulse_fast_r <= 1'b0 ;
else if (pulse_fast)
pulse_fast_r <= 1'b1 ;
end
reg [1:0] pulse_fast2s_r ;
/************ slow clk *************/
//(2) 慢时钟域对信号进行延迟打拍采样
always@(posedge clk_slow or negedge rstn) begin
if (!rstn)
pulse_fast2s_r <= 3'b0 ;
else
pulse_fast2s_r <= {pulse_fast2s_r[0], pulse_fast_r} ;
end
assign pulse_slow = pulse_fast2s_r[1] ;
reg [1:0] pulse_slow2f_r ;
/********* feedback for slow clk to fast clk *******/
//(3) 对反馈信号进行延迟打拍采样
always@(posedge clk_fast or negedge rstn) begin
if (!rstn)
pulse_slow2f_r <= 1'b0 ;
else
pulse_slow2f_r <= {pulse_slow2f_r[0], pulse_slow} ;
end
//控制快时钟域脉冲信号拉低
assign clear_n = ~(!pulse_fast && pulse_slow2f_r[1]) ;
(3)多bit慢时钟到快时钟:延迟采样法。先用延迟打拍的方法对数据使能信号进行 2 级打拍缓存,然后再在快时钟域对慢时钟域的数据信号进行采集。当频率比较大时,可配合计数器一起,在慢时钟中间采样。
该方法的基本思想是保证信号被安全采集的时刻,而不用同步多位宽的数据信号,可节省部分硬件资源。
部分Verilog:
//sync din_en,实际做同步部分
reg [1:0] din_en_r ;
always @(posedge clk2 or negedge rstn)
if (!rstn)
din_en_r <= 3'b0 ;
else
din_en_r <= {din_en_r[0], din_en} ;
//sync data,同步后的下一个周期将输出数据准备
reg [31:0] dout_r ;
reg dout_en_r ;
always @(posedge clk2 or negedge rstn)
if (!rstn) begin
dout_r <= 'b0 ;
dout_en_r <= 'b0 ;
end
else if (din_en_r[1]) begin
dout_r <= din ;
dout_en_r <= din_en_r ;
end
assign dout = dout_r ;
assign dout_en = dout_en_r ;
(4)多bit快时钟到慢时钟:同步和异步FIFO。
当多位宽数据进行同步时,如果该数据各 bit 位都可以看作电平信号,即相对一段时间内各 bit 位数据均可以保持不变以至于能被慢时钟采集到,可以消耗一些触发器资源对多位宽数据进行简单的延迟打拍同步。
但如果数据变化速率过快,就不能再使用延迟打拍采样的方法。因为此时数据各 bit 位不再是电平信号,变化的时间也参差不齐,用异步时钟进行打拍采样,可能会采集到因路径延迟不同而导致的错误数据。(要保持快时钟频率的数据发一段时间停一段时间,因为一直发的话会存满,导致数据丢失)
分配内存单位、generate块的原理、格雷码与二进制码的相互转换、格雷码与二进制码之间的关系,二进制之间加减原理
2、UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器,串行通信协议)
uart_rx模块:多级同步并捕获下降沿模块、rx_flag信号模块、波特率计数模块、接收数据计数模块、接收数据模块(根据接收数据计数接收对应bit)、接收完成模块
uart_tx模块:uart_tx_busy信号和tx_data_t(发送数据寄存器)模块、波特率计数模块、发送数据计数模块、发送数据模块(根据发送数据计数发送对应bit)
作用:设备之间传输数据,UART常见于串口通信,它负责将并行数据转换为串行数据以进行传输,并在接收端将串行数据重新转换为并行数据。
学到的知识:捕获接收端口下降沿、波特率和比特率的区别、在波特率计数中间发送保证数据传输稳定性、十六进制发送十六进制接收、串转并、并转串、按计数发送bit
3、IIC(Inter-Integrated Circuit,集成电路总线,串行通信协议)
i2c_dri模块:三态门、生成1/4倍频率的驱动时钟SCL、三段式状态机
e2prom_rw模块:E2PROM读写测试
rw_result_led模块:读写测试完成标志、测试结果提示
作用:支持多主机和多从机的通信(开始和结束由主机控制,一段数据发送结束由从机应答)
学到的知识:inout的三态门构建、产生任意频率的时钟、主从机应答控制、三段式状态机(一段时序逻辑改变cur_state、一段组合逻辑改变next_state、一段时序或组合逻辑描述当前状态行为)、自主控制时钟对数据进行操作(用计数器,如7’d3拉低,7’d4做操作,7’d5拉高,这样就实现了IIC的要求:在SCL低电平时对SDA做数据传输,因为dri_clk是scl的四倍频,所以四个周期为scl的一个周期,即scl的高低电平保持两个dri_clk周期,同时也意味着在持续两个dri_clk周期后必须将scl取反)、多次读写操作(写状态结束后跳到修改数据状态,修改完数据后再跳回写操作状态)、控制LED闪烁
参考文章:
[1]https://www.runoob.com/w3cnote/verilog2-slow2fast.html
[2]https://www.runoob.com/w3cnote/verilog2-fast2slow.html
[3]https://zhuanlan.zhihu.com/p/113832794
[4]Clifford E. Cummings,"Clock Domain Crossing (CDC) Design & VeTechniques Using SystemVerilog”