基础: 在先做23题同步FIFO和24题格雷码的前提下,写异步FIFO很简单。同步FIFO中的很多内容可以直接拿来用。 可以先看同步FIFO详解和代码 结构: 在同步FIFO基础上,进行异步FIFO设计。保持类似的读写逻辑和读写地址控制,区别是增加了格雷码跨时钟,另外空满逻辑是使用格雷码判断空满。  代码:`timescale 1ns/1ns//********************************//作者:FPGA探索者//********************************/***************************************RAM*****************************************/module dual_port_RAM #(parameter DEPTH = 16,        parameter WIDTH = 8)(  input wclk ,input wenc ,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。 ,input [WIDTH-1:0] wdata       //数据写入 ,input rclk ,input renc ,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。 ,output reg [WIDTH-1:0] rdata   //数据输出);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) begin if(wenc)  RAM_MEM[waddr] <= wdata;end always @(posedge rclk) begin if(renc)  rdata <= RAM_MEM[raddr];end endmodule  /***************************************AFIFO*****************************************/module asyn_fifo#( parameter WIDTH = 8, parameter  DEPTH = 16)( input      wclk ,  input      rclk ,    input      wrstn , input     rrstn , input      winc , input       rinc , input   [WIDTH-1:0] wdata , output wire    wfull , output wire    rempty , output wire [WIDTH-1:0] rdata);            localparam ADDR_WIDTH = $clog2(DEPTH);        reg [ADDR_WIDTH:0] waddr;    reg [ADDR_WIDTH:0] raddr;    always @ (posedge wclk&nbs***bsp;negedge wrstn) begin        if(~wrstn) begin            waddr <= 'b0;        end         else begin            if( winc && ~wfull ) begin                waddr <= waddr + 1'b1;            end             else begin                waddr <= waddr;                end         end     end         always @ (posedge rclk&nbs***bsp;negedge rrstn) begin        if(~rrstn) begin            raddr <= 'b0;        end         else begin            if( rinc && ~rempty ) begin                raddr <= raddr + 1'b1;            end             else begin                raddr <= raddr;                end         end     end         wire [ADDR_WIDTH:0] waddr_gray;    wire [ADDR_WIDTH:0] raddr_gray;    assign waddr_gray = waddr ^ (waddr>>1);    assign raddr_gray = raddr ^ (raddr>>1);        reg [ADDR_WIDTH:0] waddr_gray_reg;    always @ (posedge wclk&nbs***bsp;negedge wrstn) begin        if(~wrstn) begin            waddr_gray_reg  <= 'd0;        end        else begin            waddr_gray_reg <= waddr_gray;        end     end         reg [ADDR_WIDTH:0] raddr_gray_reg;    always @ (posedge rclk&nbs***bsp;negedge rrstn) begin        if(~rrstn) begin            raddr_gray_reg  <= 'd0;        end        else begin            raddr_gray_reg <= raddr_gray;        end     end            reg [ADDR_WIDTH:0] addr_r2w_t;    reg [ADDR_WIDTH:0] addr_r2w;    always @ (posedge wclk&nbs***bsp;negedge wrstn) begin        if(~wrstn) begin            addr_r2w_t  <= 'd0;            addr_r2w    <= 'd0;        end        else begin            addr_r2w_t <= raddr_gray_reg;            addr_r2w <= addr_r2w_t;        end     end         reg [ADDR_WIDTH:0] addr_w2r_t;    reg [ADDR_WIDTH:0] addr_w2r;    always @ (posedge rclk&nbs***bsp;negedge rrstn) begin        if(~rrstn) begin            addr_w2r_t  <= 'd0;            addr_w2r    <= 'd0;        end        else begin            addr_w2r_t <= waddr_gray_reg;            addr_w2r <= addr_w2r_t;        end     end             assign wfull = (waddr_gray_reg == {~addr_r2w[ADDR_WIDTH:ADDR_WIDTH-1], addr_r2w[ADDR_WIDTH-2:0]});    assign rempty = (raddr_gray_reg == addr_w2r);        dual_port_RAM      #(        .DEPTH(DEPTH),  .WIDTH(WIDTH)    )    dual_port_RAM_U0     (        .wclk(wclk),        .wenc(winc&&~wfull),        .waddr(waddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。     .wdata(wdata),       //数据写入        .rclk(rclk),        .renc(rinc&&~rempty),        .raddr(raddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。     .rdata(rdata)   //数据输出);        endmodule
点赞 37
评论 3
全部评论

相关推荐

03-02 08:18
集美大学 Java
钱嘛数字而已:没有赛事奖项么?另外,项目经历字有点多哈,建议突出一下重点:用的什么技术,解决什么问题,达到什么效果。
大家都开始春招面试了吗
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务