`timescale 1ns/1ns /***************************************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 ); parameter cwidth=$clog2(DEPTH); reg [cwidth:0] raddr,waddr; wire wen,ren; assign wen=winc&~wfull; assign ren=rinc&~rempty; always @(posedge wclk or negedge wrstn) begin if(!wrstn) begin waddr<=0; end else begin waddr<= wen ? waddr+1 : waddr; end end always @(posedge rclk or negedge rrstn) begin if(!rrstn) begin raddr<=0; end else begin raddr<= ren ? raddr+1 : raddr; end end wire [cwidth:0] gray_r,gray_w; assign gray_r=raddr^(raddr>>1); assign gray_w=waddr^(waddr>>1); reg[cwidth:0] gray_raddr,gary_waddr; always @(posedge wclk or negedge wrstn) begin if(!wrstn) begin gary_waddr<=0; end else begin gary_waddr<=gray_w; end end always @(posedge rclk or negedge rrstn) begin if(!rrstn) begin gray_raddr<=0; end else begin gray_raddr<=gray_r; end end reg [cwidth:0] raddr_temp0,raddr_temp1, waddr_temp0,waddr_temp1; always @(posedge wclk or negedge wrstn) begin if(!wrstn) begin raddr_temp0<=0; raddr_temp1<=0; end else begin raddr_temp0<=gray_raddr; raddr_temp1<=raddr_temp0; end end always@(posedge rclk or negedge rrstn) begin if(!rrstn) begin waddr_temp0<=0; waddr_temp1<=0; end else begin waddr_temp0<=gary_waddr; waddr_temp1<=waddr_temp0; end end assign rempty=waddr_temp1==gray_raddr; assign wfull=gary_waddr=={~raddr_temp1[cwidth:cwidth-1],raddr_temp1[cwidth-2:0] }; dual_port_RAM #(.DEPTH(DEPTH), .WIDTH(WIDTH)) u0( . wclk(wclk), . wenc(wen), . waddr(waddr[cwidth-1:0]), //深度对2取对数,得到地址的位宽。 . wdata(wdata), //数据写入 . rclk(rclk), .renc(ren), .raddr(raddr[cwidth-1:0]), //深度对2取对数,得到地址的位宽。 . rdata(rdata) //数据输出 ); endmodule
module texbench (); reg wclk,rclk,wrstn,rrstn,winc,rinc; reg [7:0]wdata; wire wfull,rempty; wire[7:0] rdata; asyn_fifo #( .WIDTH (8), .DEPTH (16) ) u0( wclk , rclk , wrstn , rrstn , winc, rinc, wdata , wfull , rempty , rdata ); integer i; initial begin #0; wclk=0; rclk=0; wrstn=0; rrstn=0; #10 wrstn=1; rrstn=1; end always #3 wclk=~wclk; always #6 rclk=~rclk; initial begin #0; winc=0; rinc=0; wdata=0; end initial begin #20; send_wr; end initial begin #100 send_rd; #100; $finish; end task send_wr; begin for (i=0;i<3;i=i+1) begin @(posedge wclk )begin winc<=1; wdata<=i+1; end end @(posedge wclk)begin winc<=0; wdata<=0; end repeat(10)@(posedge wclk); end endtask task send_rd; begin for(i=0;i<16;i=i+1) begin @(posedge rclk)begin rinc<=1; end @(posedge rclk)begin rinc<=0; end end end endtask endmodule
仿真结果如下: