FIFO的设计与仿真

本设计参照齐威王大哥的设计,采用模块化的设计方法,每个模块简单易懂,并进行了每个模块的仿真。最后进行顶层设计,编写了测试激励在modisim上仿真正确,

下面给出代码和测试激励,附上一篇比较好的英文文献。

复制代码
 1 module yibu_fifo(wclk,wreset,wdata,wena,rclk,rena,rdata,rreset,full,empty);
 2 parameter DSIZE = 8,    
 3           ASIZE = 4;
 4 input wclk,wreset,rclk,rreset;
 5 input wena,rena; //写控制信号  读控制信号
 6 input [DSIZE-1:0] wdata;  //写数据
 7 output[DSIZE-1:0] rdata;  //读数据
 8 output full,empty ;//写满 读空
 9 wire  [ASIZE:0] wzz, wzz_syn,rzz,rzz_syn;   //特别注意
10 wire  [ASIZE-1:0] raddr,waddr;              //特别注意
11 fifomem   U1(rdata, wdata, waddr, raddr, wena,full, wclk);
12 w_full    U2(full, waddr, wzz, rzz_syn, wena, wclk, wreset);
13 r_empty   U3(empty, raddr, rzz, wzz_syn, rena, rclk, rreset);
14 syn_w2r   U4(wzz,rclk,rreset,wzz_syn);
15 syn_r2w   U5(wclk,wreset,rzz,rzz_syn);
16 endmodule 
复制代码
复制代码
module fifomem (rdata, wdata, waddr, raddr, wena,full, wclk);
parameter DSIZE = 8,  
          ASIZE = 4;
input wclk;
input [DSIZE-1:0] wdata;
input wena,full;
output [DSIZE-1:0] rdata;
input [ASIZE-1:0] waddr;
input [ASIZE-1:0] raddr;
reg [DSIZE-1:0] mem[0:(1<<ASIZE)-1];  //register  
assign rdata=mem[raddr];                 //read
always @(posedge wclk)                //write
if (wena && !full)  
    mem[waddr] <= wdata;   
endmodule 
复制代码
复制代码
module r_empty(empty, raddr, rzz, wzz_syn, rena, rclk, rreset);
parameter DSIZE = 8,  
          ASIZE = 4;  //
input rclk, rreset,rena;
input [ASIZE:0] wzz_syn;
output [ASIZE:0] rzz;
output [ASIZE-1:0] raddr;
output empty;
reg empty;
reg [ASIZE:0] rzz;
reg [ASIZE:0] rbin;
wire [ASIZE:0] rgraynext,rbinnext;
//-------------empty产生与raddr产生-------------------  
always @(posedge rclk or negedge rreset) // GRAYSTYLE2 pointer  
begin 
    if (!rreset)  
        {rbin, rzz} <= 0;  
    else 
        {rbin, rzz} <= {rbinnext, rgraynext};  
end   
// Memory read-address pointer (okay to use binary to address memory)  
assign raddr = rbin[ASIZE-1:0];  
assign rbinnext = rbin + (rena & ~empty);  
assign rgraynext = (rbinnext>>1) ^ rbinnext;  
  
// FIFO empty when the next rptr == synchronized wptr or on reset  
assign rempty_val = (rgraynext == wzz_syn);  
always @(posedge rclk or negedge rreset)  
begin 
    if (!rreset)  
        empty <= 1'b1;  
    else 
        empty <= rempty_val;  
end 
endmodule 
复制代码
复制代码
module w_full(full, waddr, wzz, rzz_syn, wena, wclk, wreset);
parameter DSIZE = 8,  
          ASIZE = 4;
input wclk,wreset;
input wena;
input [ASIZE:0] rzz_syn;
output [ASIZE:0] wzz;
output full;
output [ASIZE-1:0] waddr;
reg full;
reg  [ASIZE:0] wzz;
reg [ASIZE:0] wbin;
wire [ASIZE:0] wgraynext,wbinnext;
//---------------full产生与waddr产生--------------------
always @(posedge wclk or negedge wreset)  
    if (!wreset)  
        {wbin, wzz} <= 0;  
    else 
        {wbin, wzz} <= {wbinnext, wgraynext};  
// Memory write-address pointer (okay to use binary to address memory)  
assign waddr = wbin[ASIZE-1:0];  
assign wbinnext = wbin + (wena & ~full); 
 
assign wgraynext = (wbinnext>>1) ^ wbinnext; //bin to g 
assign wfull_val = (wgraynext=={~rzz_syn[ASIZE:ASIZE-1], rzz_syn[ASIZE-2:0]}); //  full   
  
always @(posedge wclk or negedge wreset)  
    if (!wreset)  
        full <= 1'b0;  
    else 
        full <= wfull_val;       
endmodule 
复制代码
复制代码
module syn_r2w(wclk,wreset,rzz,rzz_syn);
 parameter DSIZE = 8,  
          ASIZE = 4;
input wclk,wreset;
input [ASIZE:0] rzz;
output [ASIZE:0] rzz_syn;
reg [ASIZE:0] rzz_syn;
reg [ASIZE:0]  rzz_syn_1;   //两级同步
always @(posedge wclk or negedge wreset)
if(!wreset)
{rzz_syn,rzz_syn_1} <= 0;
else 
{rzz_syn,rzz_syn_1} <= {rzz_syn_1,rzz};
endmodule 
 
复制代码
复制代码
module syn_w2r (wzz,rclk,rreset,wzz_syn);
parameter DSIZE = 8,  
          ASIZE = 4;
input rclk,rreset;
input [ASIZE:0] wzz;
output [ASIZE:0] wzz_syn;
reg  [ASIZE:0] wzz_syn;
reg [ASIZE:0] wzz_syn_1;    //两级同步
always @(posedge rclk or negedge rreset)  
    if (!rreset)  
        {wzz_syn,wzz_syn_1} <= 0;  
    else 
        {wzz_syn,wzz_syn_1} <= {wzz_syn_1,wzz};         
endmodule 
复制代码
复制代码
module testbench;
reg wclk,wreset;
reg rclk,rreset;
reg rena;
reg wena;
wire full;
wire empty;
reg [7:0] wdata;
wire [7:0] rdata;
reg [7:0]    value;
yibu_fifo    FIFO(wclk,wreset,wdata,wena,rclk,rena,rdata,rreset,full,empty);
// read
task read_word;
begin
   @(negedge rclk);
   rena = 1;
   @(posedge rclk)
   #5;
   rena = 0;
end
endtask
//write
task write_word;
input [7:0]    value;
begin
   @(negedge wclk);
   wdata = value;
   wena = 1;
   @(posedge wclk);
   #5;
   wdata = 8'hzz;
   wena = 0;
end
endtask
//write clock
initial begin
   wclk = 0;
   forever begin
      #5 wclk = 1;
      #5 wclk = 0;
   end
end
//read clock
initial begin
   rclk = 0;
   forever begin
      #10 rclk = 1;
      #10 rclk = 0;
   end
end
// process
initial 
begin
  test1; 
end
task test1;
begin
   wdata = 8'hzz;
   wena = 0;
   rena = 0;
   wreset = 0;
   rreset= 0;
   #10 wreset = 1;rreset=1;
   #50;
    //写入10个数据
   write_word (8'h01);
   write_word (8'h02);   //正常
   write_word (8'h03);   
   write_word (8'h04); 
   write_word (8'h05); 
   write_word (8'h06); 
   write_word (8'h07); 
   write_word (8'h08); 
   write_word (8'h09); 
   write_word (8'h0A); 
   repeat (10) 
   begin
      read_word;   // read 10
   end
write_word (8'h01);
write_word (8'h02);
write_word (8'h03);
write_word (8'h04);
write_word (8'h05);
write_word (8'h06);
write_word (8'h07);
write_word (8'h08);
write_word (8'h09);
write_word (8'h0A);
write_word (8'h0B);
write_word (8'h0C);
write_word (8'h0D);
write_word (8'h0E);
write_word (8'h0F);
write_word (8'h10);
write_word (8'h11);
write_word (8'h12);
write_word (8'h13); //    写满溢出
   repeat (16) 
   begin
      read_word;   // 读空  
   end
end 
endtask
endmodule 
复制代码

2013-03-24

英文文献http://www.sunburst-design.com/papers/

原文地址:https://www.cnblogs.com/lueguo/p/3357499.html