主函数:
module SYN_FIFO #( parameter DATA_WIDTH=8, parameter ADDR_WIDTH=4, parameter DATA_DEPTH=1<<ADDR_WIDTH ) ( input clk, //时钟 input rst_n, //复位信号输入 input rd_en, //读取使能信号 input wr_en, //写使能信号 input [DATA_WIDTH-1'b1:0]data_w, //写入数据 output reg [DATA_WIDTH-1:0]data_r, //读出数据 output reg [ADDR_WIDTH-1:0] wr_cnt, //写计数器 output reg [ADDR_WIDTH-1:0] rd_cnt, //读计数器 output fifo_full, //fifo满 output reg [ADDR_WIDTH-1'b1:0]status_cnt, output fifo_empty //fifo空标志 ); reg [DATA_WIDTH-1:0]data_ram; //-------------- assign fifo_full = (status_cnt==DATA_DEPTH-1); assign fifo_empty = (status_cnt==0); //读取使能寄存 reg rd_en_r; always@(posedge clk or negedge rst_n) if(~rst_n) rd_en_r<=1'b0; else rd_en_r<=rd_en; //写入数据计数器 always@(posedge clk or negedge rst_n) if(~rst_n) wr_cnt<=4'hf; else if(wr_cnt==DATA_DEPTH-1'b1) wr_cnt<=0; else if(wr_en) wr_cnt<=wr_cnt+1'b1; //读取计数器 always@(posedge clk or negedge rst_n) if(~rst_n) rd_cnt<=0; else if(rd_cnt==DATA_DEPTH-1'b1) rd_cnt<=0; else if(rd_en) rd_cnt<=rd_cnt+1'b1; always@(posedge clk or negedge rst_n) if(~rst_n) data_r<=4'hf; else if(rd_en_r) data_r<=data_ram; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin status_cnt <= 0; end else if(rd_en && !wr_en && (status_cnt != 0))begin status_cnt <= status_cnt - 1; end else if(wr_en && !rd_en && (status_cnt != DATA_DEPTH-1)) status_cnt <= status_cnt + 1; else status_cnt <= status_cnt; end //Syn_Dual_Port_RAM integer i; reg [DATA_WIDTH-1:0] register[DATA_DEPTH-1:0]; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin for(i = 0; i < DATA_DEPTH; i = i + 1) register[i] <= 0; end else if(wr_en == 1'b1) register[wr_cnt] <= data_w; end always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin data_ram <= 0; end else if(rd_en == 1'b1) data_ram <= register[rd_cnt]; else data_ram <= data_ram; end endmodule
仿真:
`timescale 1ns/1ps module fifo_tb; parameter DATA_WIDTH=8; parameter ADDR_WIDTH=4; parameter DATA_DEPTH=1<<ADDR_WIDTH; reg clk, rst_n,rd_en, wr_en; reg [15:0]data_w; //写入数据 wire [DATA_WIDTH-1:0]data_r; //读出数据 wire [ADDR_WIDTH-1:0] wr_cnt; //写计数器 wire [ADDR_WIDTH-1:0] rd_cnt; //读计数器 wire fifo_full; wire[ADDR_WIDTH-1'b1:0]ptr; wire fifo_empty ; SYN_FIFO u0( clk, //时钟 rst_n, //复位信号输入 rd_en, //读取使能信号 wr_en, //写使能信号 data_w, //写入数据 data_r, //读出数据 wr_cnt, //写计数器 rd_cnt, //读计数器 fifo_full, //fifo满 ptr, fifo_empty //fifo空标志 ); initial begin clk=0; forever #10 clk=~clk; end initial begin rst_n=0; data_w=16'd0; rd_en=0; wr_en=0; #20; rst_n=1; #20; wr(0); wr(1); wr(2); wr(3); wr(4); wr(5); wr(6); wr(7); wr(8); wr(9); wr(10); wr(11); wr(12); wr(13); wr(14); wr(15); #20; rd; #20; $stop; end task wr; input[3:0] i; begin wr_en=1'b1; data_w=i; #20; wr_en=1'b0; end endtask task rd; begin rd_en=1'b1; #(20*17); rd_en=1'b0; end endtask endmodule