同步FIFO设计及仿真

主函数:

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

猜你喜欢

转载自www.cnblogs.com/luxinshuo/p/13406709.html