近日复习数字电路设计,遇到异步FIFO的问题。
在百度找到相关代码,阅读理解后,写出注释,方便自己今后查阅以及迅速理解;同时在此分享,以便广大读者查阅。
并,感谢分享者的无私精神!
此异步FIFO,深度256,宽度8;
类似数组,以数组举例:深度256,表示数组存放256个数据;宽度8,表示每个数据为8位二进制;
采用格雷码进行空满条件判断,
原因是格雷码相邻的数据只变化一位,可以减少相邻物理信号线同时变化的情况,减少电路串扰的可能,减少电路中的噪声。
注意:
格雷码判空,直接判断读写地址是否相同即可;
格雷码判满,需要满足条件:最高位不同,次高位也不同,其余位必须相同;所以,需要将信号最高2位翻转,其余不变;
module FIFO(Wr_Clk, nWr, Din, Rd_Clk, nRd, Dout, Full, Empty); input Wr_Clk, nWr, Rd_Clk, nRd; input [Bsize-1:0] Din; output [Bsize-1:0] Dout; output Full, Empty; reg Full, Empty; reg [Bsize-1:0] Buff [Dsize-1:0]; reg [Asize:0] Wr_Addr_Bin, Rd_Addr_Bin; reg [Asize:0] Sync_Wr_Addr0_Gray, Sync_Wr_Addr1_Gray, Sync_Wr_Addr2_Gray; reg [Asize:0] Sync_Rd_Addr0_Gray, Sync_Rd_Addr1_Gray, Sync_Rd_Addr2_Gray; wire [Asize-1:0] FIFO_Entry_Addr, FIFO_Exit_Addr; wire [Asize:0] Wr_NextAddr_Bin, Rd_NextAddr_Bin; wire [Asize:0] Wr_NextAddr_Gray, Rd_NextAddr_Gray; wire Asyn_Full, Asyn_Empty; parameter Dsize = 256, Asize = 8, Bsize = 8; initial begin Full = 0; Empty = 1; Wr_Addr_Bin = 0; Rd_Addr_Bin = 0; Sync_Wr_Addr0_Gray = 0; Sync_Wr_Addr1_Gray = 0; Sync_Wr_Addr2_Gray = 0; Sync_Rd_Addr0_Gray = 0; Sync_Rd_Addr1_Gray = 0; Sync_Rd_Addr2_Gray = 0; end assign FIFO_Exit_Addr = Rd_Addr_Bin[Asize-1:0]; assign FIFO_Entry_Addr = Wr_Addr_Bin[Asize-1:0]; assign Dout = Buff[FIFO_Exit_Addr]; always @ (posedge Wr_Clk) begin if (~nWr & ~Full) Buff[FIFO_Entry_Addr] <= Din; else Buff[FIFO_Entry_Addr] <= Buff[FIFO_Entry_Addr]; end assign Wr_NextAddr_Bin = (~nWr&~Full) ?Wr_Addr_Bin[Asize:0]+1:Wr_Addr_Bin[Asize:0]; assign Rd_NextAddr_Bin = (~nRd&~Empty)?Rd_Addr_Bin[Asize:0]+1:Rd_Addr_Bin[Asize:0]; assign Wr_NextAddr_Gray = (Wr_NextAddr_Bin >> 1) ^ Wr_NextAddr_Bin; assign Rd_NextAddr_Gray = (Rd_NextAddr_Bin >> 1) ^ Rd_NextAddr_Bin; always @ (posedge Wr_Clk) begin Wr_Addr_Bin <= Wr_NextAddr_Bin; Sync_Wr_Addr0_Gray <= Wr_NextAddr_Gray; end always @ (posedge Rd_Clk) begin Rd_Addr_Bin <= Rd_NextAddr_Bin; Sync_Rd_Addr0_Gray <= Rd_NextAddr_Gray; end always @ (posedge Wr_Clk) begin Sync_Rd_Addr2_Gray <= Sync_Rd_Addr1_Gray; Sync_Rd_Addr1_Gray <= Sync_Rd_Addr0_Gray; end always @ (posedge Rd_Clk) begin Sync_Wr_Addr2_Gray <= Sync_Wr_Addr1_Gray; Sync_Wr_Addr1_Gray <= Sync_Wr_Addr0_Gray; end assign Asyn_Empty = (Rd_NextAddr_Gray==Sync_Wr_Addr2_Gray); assign Asyn_Full = (Wr_NextAddr_Gray=={~Sync_Rd_Addr2_Gray[Asize:Asize-1], Sync_Rd_Addr2_Gray[Asize-2:0]}); always @ (posedge Wr_Clk) begin Full <= Asyn_Full; end always @ (posedge Rd_Clk) begin Empty <= Asyn_Empty; endendmodule
近日复习数字电路设计,遇到异步FIFO的问题。
在百度找到相关代码,阅读理解后,写出注释,方便自己今后查阅以及迅速理解;同时在此分享,以便广大读者查阅。
并,感谢分享者的无私精神!
此异步FIFO,深度256,宽度8;
类似数组,以数组举例:深度256,表示数组存放256个数据;宽度8,表示每个数据为8位二进制;
采用格雷码进行空满条件判断,
原因是格雷码相邻的数据只变化一位,可以减少相邻物理信号线同时变化的情况,减少电路串扰的可能,减少电路中的噪声。
注意:
格雷码判空,直接判断读写地址是否相同即可;
格雷码判满,需要满足条件:最高位不同,次高位也不同,其余位必须相同;所以,需要将信号最高2位翻转,其余不变;
module FIFO(Wr_Clk, nWr, Din, Rd_Clk, nRd, Dout, Full, Empty); input Wr_Clk, nWr, Rd_Clk, nRd; input [Bsize-1:0] Din; output [Bsize-1:0] Dout; output Full, Empty; reg Full, Empty; reg [Bsize-1:0] Buff [Dsize-1:0]; reg [Asize:0] Wr_Addr_Bin, Rd_Addr_Bin; reg [Asize:0] Sync_Wr_Addr0_Gray, Sync_Wr_Addr1_Gray, Sync_Wr_Addr2_Gray; reg [Asize:0] Sync_Rd_Addr0_Gray, Sync_Rd_Addr1_Gray, Sync_Rd_Addr2_Gray; wire [Asize-1:0] FIFO_Entry_Addr, FIFO_Exit_Addr; wire [Asize:0] Wr_NextAddr_Bin, Rd_NextAddr_Bin; wire [Asize:0] Wr_NextAddr_Gray, Rd_NextAddr_Gray; wire Asyn_Full, Asyn_Empty; parameter Dsize = 256, Asize = 8, Bsize = 8; initial begin Full = 0; Empty = 1; Wr_Addr_Bin = 0; Rd_Addr_Bin = 0; Sync_Wr_Addr0_Gray = 0; Sync_Wr_Addr1_Gray = 0; Sync_Wr_Addr2_Gray = 0; Sync_Rd_Addr0_Gray = 0; Sync_Rd_Addr1_Gray = 0; Sync_Rd_Addr2_Gray = 0; end assign FIFO_Exit_Addr = Rd_Addr_Bin[Asize-1:0]; assign FIFO_Entry_Addr = Wr_Addr_Bin[Asize-1:0]; assign Dout = Buff[FIFO_Exit_Addr]; always @ (posedge Wr_Clk) begin if (~nWr & ~Full) Buff[FIFO_Entry_Addr] <= Din; else Buff[FIFO_Entry_Addr] <= Buff[FIFO_Entry_Addr]; end assign Wr_NextAddr_Bin = (~nWr&~Full) ?Wr_Addr_Bin[Asize:0]+1:Wr_Addr_Bin[Asize:0]; assign Rd_NextAddr_Bin = (~nRd&~Empty)?Rd_Addr_Bin[Asize:0]+1:Rd_Addr_Bin[Asize:0]; assign Wr_NextAddr_Gray = (Wr_NextAddr_Bin >> 1) ^ Wr_NextAddr_Bin; assign Rd_NextAddr_Gray = (Rd_NextAddr_Bin >> 1) ^ Rd_NextAddr_Bin; always @ (posedge Wr_Clk) begin Wr_Addr_Bin <= Wr_NextAddr_Bin; Sync_Wr_Addr0_Gray <= Wr_NextAddr_Gray; end always @ (posedge Rd_Clk) begin Rd_Addr_Bin <= Rd_NextAddr_Bin; Sync_Rd_Addr0_Gray <= Rd_NextAddr_Gray; end always @ (posedge Wr_Clk) begin Sync_Rd_Addr2_Gray <= Sync_Rd_Addr1_Gray; Sync_Rd_Addr1_Gray <= Sync_Rd_Addr0_Gray; end always @ (posedge Rd_Clk) begin Sync_Wr_Addr2_Gray <= Sync_Wr_Addr1_Gray; Sync_Wr_Addr1_Gray <= Sync_Wr_Addr0_Gray; end assign Asyn_Empty = (Rd_NextAddr_Gray==Sync_Wr_Addr2_Gray); assign Asyn_Full = (Wr_NextAddr_Gray=={~Sync_Rd_Addr2_Gray[Asize:Asize-1], Sync_Rd_Addr2_Gray[Asize-2:0]}); always @ (posedge Wr_Clk) begin Full <= Asyn_Full; end always @ (posedge Rd_Clk) begin Empty <= Asyn_Empty; endendmodule
0 0