开发区网站建设工作职责合肥瑶海区地图全图高清版

当前位置: 首页 > news >正文

开发区网站建设工作职责,合肥瑶海区地图全图高清版,微信支付 网站备案,莱芜网站快排相关文章 数字IC前端学习笔记#xff1a;LSFR#xff08;线性反馈移位寄存器#xff09; 数字IC前端学习笔记#xff1a;跨时钟域信号同步 数字IC前端学习笔记#xff1a;信号同步和边沿检测 数字IC前端学习笔记#xff1a;锁存器Latch的综合 数字IC前端学习笔记LSFR线性反馈移位寄存器 数字IC前端学习笔记跨时钟域信号同步 数字IC前端学习笔记信号同步和边沿检测 数字IC前端学习笔记锁存器Latch的综合 数字IC前端学习笔记格雷码含Verilog实现的二进制格雷码转换器 数字IC前端学习笔记FIFO的Verilog实现一 目录 4.异步FIFO原理 5.异步FIFO的Verilog实现 4.异步FIFO原理 在之前我们讨论了了同步FIFO因为其具有单一的时钟因此应用范围有限。在实际的引用中我们经常遇到多个时钟域的情况此时数据需要在两个时钟域之间实现传送并且不能出现毛刺和亚稳态。我们以PCIe插槽上的以太网适配器板卡为例加以说明。该板卡从局域网(LAN)或以太网接收数据包然后将数据传送给系统存储器。反过来它从系统存储器接受数据包然后传送给网络。板卡的一侧和网络通信用以太网本地处理相关操作。板卡的另一侧与PCEe接口交互以板卡自身的时钟工作。这两个时钟不仅频率不同而且是异步的频率不是倍数关系如果石是倍数关系可以认为这是同步时钟因为相位差恒定。此时需要使用异步FIFO将数据从一个时钟域传送到另一个时钟域。 尽管异步FIFO的操作原理与同步FIFO类似但由于前者与两个时钟有关电路的复杂度也会增加。对异步FIFO进行数据写入和读出操作的方式与同步FIFO极其相似写入与读出操作也有自己的信号集其复杂度主要体现于产生FIFO_full、FIFO_empty、room_avaliable、data_avaliable等标识。异步FIFO中产生这些标识的方法比同步FIFO中要复杂得多。 在这里我们不能使用计数器根据读取或存储信号保存FIFO中的数据量因为他们是两个时钟域的信号不能用两个时钟对同一个reg赋值。我们知道当FIFO为满或空时写入指针和读取指针是相等的。但这是不够的我们需要另外的条件将“空”和“满”进行区分。前面介绍过FIFO工作时写入指针在前读出指针跟随写入指针。当FIFO为满时写入指针的状态是到达顶部后返回底部最后和读取指针相同即超越读取指针一轮FIFO深度如果我们在指针最高位增加一个辅助位给写入和读取指针则可以用来指示当这两个指针相同不包括辅助位时是没有超越的相同还是超越一轮的相同。 我们以一个深度为4的FIFO为例说明。此时计数器需要两位表示计数序列为00→01 10→11→00在最高位增加一位辅助位后计数序列为000→001→010→011→100→101→110 →111。正如我们所看到的除了最高位辅助位其他位将循环两次通过比较辅助位我们就可以判断FIFO状态是满还是空。 虽然解决了空满状态的标识但仍然存在问题即读指针和写指针分别产生于各自时钟域不能互相比较否则会因时序问题产生亚稳态。解决这个问题的办法是将指针从一个时钟域传递到另一个时钟域然后做比较。而且我们要注意传递的是多位信号而不是一位信号此时需要使用格雷码编码和译码电路将指针进行跨时钟域安全传送。在格雷码编码方案中相邻编码中只有一位发生变化该特性被用于跨时钟域矢量传递还有其他方法可见数字IC前端学习笔记跨时钟域信号同步一文。我们将所有这些零散的知识放在一个图中以便于浏览和理解具体的操作方法如下图所示。 写指针被转换为格雷码编码并经过触发器保存然后经过两级寄存器同步到读时钟域并解码为二进制编码最后与读指针比教产生fifo_empty信号。读指针的行为类似在写时钟域产生fifo_full信号。 需要注意的是当读指针被传送到写入时钟域时相对于读时钟域的读指针来说可能会存在3到4个周期的延时也就是说可能出现读指针已经增加而在写时钟域看来并未增加这会导致fifo在仍有空位时给出fifo_full信号这是异步FIFO保守的一面如此可以确保不产生数据上溢。 写指针也有类似问题会出现FIFO仍有数据而FIFO给出fifo_empty信号的情况。这些不会影响FIFO的正确操作在停止写入和读出后几个周期时就可以给出正确的fifo_emty和fifo_full信号。 5.异步FIFO的Verilog实现 module asynch_fifo #(parameter FIFO_PTR4,FIFO_WIDTH32)(wrclk, rstb_wrclk,write_en, write_data,snapshot_wrptr, rollback_wrptr,reset_wrptr,rdclk, rstb_rdclk,read_en, read_data,snapshot_rdptr, rollback_rdptr,reset_rdptr,fifo_full, fifo_empty,room_avail, data_avail);input wrclk;input rstb_wrclk;input write_en;input [FIFO_WIDTH-1:0] write_data;input snapshot_wrptr; //记录写指针快照input rollback_wrptr; //恢复写指针快照input reset_wrptr; //写指针重置为0input rdclk;input rstb_rdclk;input read_en;output [FIFO_WIDTH-1:0] read_data;input snapshot_rdptr; //记录读指针快照input rollback_rdptr; //恢复读指针快照input reset_rdptr; //读指针重置为0output reg fifo_full, fifo_empty;output reg [FIFO_PTR:0] room_avail, data_avail;localparam FIFO_DEPTH 1 FIFO_PTR //2^FIFO_PTRlocalparam FIFO_TWICEDEPTH_MINUS1 2*FIFO_DEPTH - 1reg [FIFO_PTR:0] wr_ptr_wab, wr_ptr_wab_nxt;//有辅助位的写指针wire [FIFO_PTR:0] room_avail_nxt, data_avail_nxt; reg [FIFO_PTR:0] wr_ptr_snapshot_value;wire [FIFO_PTR:0] wr_ptr_snapshot_value_nxt;wire fifo_full_nxt, fifo_empty_nxt;reg [FIFO_PTR:0] rd_ptr_snapshot_value;wire [FIFO_PTR:0] rd_ptr_snapshot_value_nxt; wire [FIFO_PTR-1:0] wr_ptr,rd_ptr;reg [FIFO_PTR:0] rd_ptr_wab, rd_ptr_wab_nxt;//有辅助位的读指针 //写指针控制逻辑 //*******************************************always(*) beginwr_ptr_wab_nxtwr_ptr_wab;if(reset_wrptr)wr_ptr_wab_nxt 0;else if(rollback_wrptr)wr_ptr_wab_nxt wr_ptr_snapshot_value;else if(write_en (wr_ptr_wab FIFO_TWICEDEPTH_MINUS1))wr_ptr_wab_nxt 0;else if(write_en)wr_ptr_wab_nxt wr_ptr_wab 1;end//写指针快照//****************************************assign wr_ptr_snapshot_value_nxt snapshot_wrptr ? wr_ptr_wab : wr_ptr_snapshot_value;//寄存器操作//***************************************always(posedge wrclk or negedge rstb_wrclk) beginif(!rstb_wrclk)beginwr_ptr_wab 0;wr_ptr_snapshot_value 0;end else beginwr_ptr_wab wr_ptr_wab_nxt;wr_ptr_snapshot_value wr_ptr_snapshot_value_nxt;endend//写指针二进制转格雷码//***************************************reg [FIFO_PTR:0] wr_ptr_wab_gray;wire [FIFO_PTR:0] wr_ptr_wab_gray_nxt;//实例化转码模块在之前的文章中已设计binary_to_gray #(.PTR(FIFO_PTR)) binary_to_gray_wr(.binary (wr_ptr_wab_nxt),.gray_value (wr_ptr_wab_gray_nxt));always(posedge wrclk or negedge rstb_wrclk)beginif(!rst_wrclk)wr_ptr_wab_gray 0;else wr_ptr_wab_gray wr_ptr_wab_gray_nxt;end//写指针同步到读时钟域//***************************************reg [FIFO_PTR:0] wr_ptr_wab_gray_sync1;reg [FIFO_PTR:0] wr_ptr_wab_gray_sync2;always(posedge rdclk or negedge rstb_rdclk) beginif(!rstb_rdclk) beginwr_ptr_wab_gray_sync1 0;wr_ptr_wab_gray_sync2 0;elsewr_ptr_wab_gray_sync1 wr_ptr_wab_gray;wr_ptr_wab_gray_sync2 wr_ptr_wab_gray_sync1;endend//格雷码写指针转二进制//***************************************reg [FIFO_PTR:0] wr_ptr_wab_rdclk;wire [FIFO_PTR:0] wr_ptr_wab_rdclk_nxt;gray_to_binary #(.PTR(FIFO_PTR)) gray_to_binary_wr(.gray_value(wr_ptr_wab_gray_sync2),.binary(wr_ptr_wab_rdclk_nxt));always(posedge rdclk or negedge rstb_rdclk) beginif(!rstb_rdclk) beginwr_ptr_wab_rdclk 0;elsewr_ptr_wab_rdclk wr_ptr_wab_rdclk_nxt;endend//读指针控制逻辑 //****************************************always(*) beginrd_ptr_wab_nxtrd_ptr_wab;if(reset_rdptr)rd_ptr_wab_nxt 0;else if(rollback_rdptr)rd_ptr_wab_nxt rd_ptr_snapshot_value;else if(read_en (rd_ptr_wab FIFO_TWICEDEPTH_MINUS1))rd_ptr_wab_nxt 0;else if(read_en)rd_ptr_wab_nxt rd_ptr_wab 1;end//读指针快照//****************************************assign rd_ptr_snapshot_value_nxt snapshot_rdptr ? rd_ptr_wab : rd_ptr_snapshot_value;//寄存器操作//***************************************always(posedge rdclk or negedge rstb_rdclk) beginif(!rstb_rdclk)beginrd_ptr_wab 0;rd_ptr_snapshot_value 0;end else beginrd_ptr_wab rd_ptr_wab_nxt;rd_ptr_snapshot_value rd_ptr_snapshot_value_nxt;endend/读指针二进制转格雷码//***************************************reg [FIFO_PTR:0] rd_ptr_wab_gray;wire [FIFO_PTR:0] rd_ptr_wab_gray_nxt;//实例化转码模块在之前的文章中已设计binary_to_gray #(.PTR(FIFO_PTR)) binary_to_gray_rd(.binary (rd_ptr_wab_nxt),.gray_value (rd_ptr_wab_gray_nxt));always(posedge rdclk or negedge rstb_rdclk)beginif(!rst_rdclk)rd_ptr_wab_gray 0;else rd_ptr_wab_gray rd_ptr_wab_gray_nxt;end//读指针同步到写时钟域//***************************************reg [FIFO_PTR:0] rd_ptr_wab_gray_sync1;reg [FIFO_PTR:0] rd_ptr_wab_gray_sync2;always(posedge wrclk or negedge rstb_wrclk) beginif(!rstb_wrclk) beginrd_ptr_wab_gray_sync1 0;rd_ptr_wab_gray_sync2 0;elserd_ptr_wab_gray_sync1 rd_ptr_wab_gray;rd_ptr_wab_gray_sync2 rd_ptr_wab_gray_sync1;endend//格雷码读指针转二进制//***************************************reg [FIFO_PTR:0] rd_ptr_wab_rdclk;wire [FIFO_PTR:0] rd_ptr_wab_rdclk_nxt;gray_to_binary #(.PTR(FIFO_PTR)) gray_to_binary_rd(.gray_value(rd_ptr_wab_gray_sync2),.binary(rd_ptr_wab_rdclk_nxt));always(posedge wrclk or negedge rstb_wrclk) beginif(!rstb_wrclk) rd_ptr_wab_rdclk 0;elserd_ptr_wab_rdclk rd_ptr_wab_wrclk_nxt;endassign wr_ptr wr_ptr_wab[FIFO_PTR-1:0];assign rd_ptr rd_ptr_wab[FIFO_PTR-1:0];//SRAM 存储器实例化//***************************************sram #(.FIFO_PTR(FIFO_PTR),.FIFO_WIDTH(FIFO_WIDTH)) sram_0(.wrclk(wrclk),.wren(write_en),.wrptr(wr_ptr),.wrdata(write_data),.rdclk(rdclk),.rden(read_en),.rdptr(rd_ptr),.rddata(read_data));//fifo_full和room_avail信号产生//***************************************assign fifo_full_nxt (wr_ptr_wab_nxt[FIFO_PTR] ! rd_ptr_wab_wrclk_nxt[FIFO_PTR])(wr_ptr_wab_nxt[FIFO_PTR-1:0] rd_ptr_wab_wrclk_nxt[FIFO_PTR-1:0]);assign room_avail_nxt (wr_ptr_wab_nxt[FIFO_PTR] rd_ptr_wab_wrclk_nxt[FIFO_PTR])?(FIFO_DEPTH-(wr_ptr_wab_nxt[FIFO_PTR-1:0] - rd_ptr_wab_wrclk_nxt[FIFO_PTR-1:0])):(rd_ptr_wab_wrclk_nxt[FIFO_PTR-1:0] - wr_ptr_wab_nxt[FIFO_PTR-1:0]); always(posedge wrclk or negedge rstb_wrclk) beginif(!rstb_wrclk) beginfifo_full 0;room_avail 0;end else beginfifo_full fifo_full_nxt;room_avail room_avail_nxt;endend //如果两者没有差一轮则指针相减代表着FIFO内数据量用深度减去数据量则为剩余空间否则直接相减不包括辅助位就可得到剩余空间//fifo_empty和room_empty信号产生//******************************************assign fifo_empty_nxt (rd_ptr_wab_nxt[FIFO_PTR] ! wr_ptr_wab_rdclk_nxt[FIFO_PTR])(rd_ptr_wab_nxt[FIFO_PTR-1:0] wr_ptr_wab_dclk_nxt[FIFO_PTR-1:0]);assign data_avail_nxt (rd_ptr_wab_nxt[FIFO_PTR] wr_ptr_wab_rdclk_nxt[FIFO_PTR])?(FIFO_DEPTH-(rd_ptr_wab_nxt[FIFO_PTR-1:0] - wr_ptr_wab_rdclk_nxt[FIFO_PTR-1:0])):(wr_ptr_wab_rdclk_nxt[FIFO_PTR-1:0] - rd_ptr_wab_nxt[FIFO_PTR-1:0]); always(posedge rdclk or negedge rstb_rdclk) beginif(!rstb_rdclk) beginfifo_empty 0;data_avail 0;end else beginfifo_empty fifo_empty_nxt;data_avail data_avail_nxt;endend endmodule 以上内容来源于《Verilog高级数字系统设计技术和实例分析》