`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 /**********************************SFIFO************************************/ module sfifo#( parameter WIDTH = 8, parameter DEPTH = 16 )( input clk , input rst_n , input winc , input rinc , input [WIDTH-1:0] wdata , output reg wfull , output reg rempty , output wire [WIDTH-1:0] rdata ); parameter depth=$clog2(DEPTH); reg [depth:0] waddr,raddr; wire renc,wenc; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wfull<=0; rempty<=0; end else if(waddr !=raddr) begin wfull <= waddr[depth-1:0]==raddr[depth-1:0]; rempty<=0; end else begin rempty<= waddr==raddr; wfull<=0; end end assign renc=rinc&~rempty; assign wenc=winc&~wfull; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin waddr<=0; raddr<=0; end else begin waddr<= wenc ? waddr+1: waddr; raddr<= renc ? raddr+1: raddr; end end dual_port_RAM #(.DEPTH (DEPTH), .WIDTH (WIDTH)) u0( .wclk(clk), .rclk(clk), .wenc(wenc), .renc(renc), .waddr(waddr[depth-1:0]), .raddr(raddr[depth-1:0]), .wdata(wdata), .rdata(rdata) ); endmodule
module texbench (); reg clk,rst_n,winc,rinc; reg [7:0]wdata; wire wfull,rempty; wire[7:0] rdata; sfifo #( .WIDTH (8), .DEPTH (16) ) u0( clk , rst_n , winc , rinc , wdata , wfull , rempty , rdata ); integer i; initial begin #0; clk=0; rst_n=0; #10 rst_n=1; end always #5 clk=~clk; initial begin #0; winc=0; rinc=0; wdata=0; end initial begin #20; send_wr; end initial begin #100 send_rd; #1000; $finish; end task send_wr; begin for (i=0;i<8;i=i+1) begin @(posedge clk )begin winc<=1; wdata<=i+1; end end @(posedge clk)begin winc<=0; wdata<=0; end repeat(10)@(posedge clk); end endtask task send_rd; begin for(i=0;i<8;i=i+1) begin @(posedge clk)begin rinc<=1; end @(posedge clk)begin rinc<=0; end end end endtask endmodule
仿真结果如下: