【异步fifo要求用verilog编写】
文章插图
module FIFO(Wr_Clk,//write FIFO clock nWr, //write FIFO signal Din, //write FIFO data Rd_Clk,//read FIFO clock nRd, //read FIFO signal Dout, //read FIFO data Full, // 1 = FIFO full Empty);// 1 = FIFO 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////////////////////FIFO数据的写入与输出////////////////////////////////////// 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///////////////////FIFO读写的地址生成器/////////////////////////////////////// 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/////////////////将产生的Full信号和Empty信号同步的各自的时钟域上////////////// 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; end//////////////////////////////////////////////////////////////////////////////endmodule
推荐阅读
- 苹果手机不断要求输入密码 方法步骤
- 日本签证要求哪些资产证明 日本签证多久能办下来
- 小篆体字
- 明星助理的要求学历吗 助理是干什么的
- 抖店入驻必须要商标注册证吗?有什么要求?
- 小红书种草有粉丝要求吗?有哪些条件?
- 玩dnf电脑最低配置 官方配置要求
- 美国亚马逊打托要求是什么?规范是什么?
- 父为子纲什么意思 怎么理解父为子纲的意思
- 结婚伴娘有什么要求