⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_fifo.txt

📁 一个verilog语言描写的同步fifo,包括:Fifo using declared registers for storage和Fifo using (model of) standard mem
💻 TXT
字号:

`define fifo_size_lg 10
`define fifo_size (1<<`fifo_size_lg)
`define fifo_addr_bits (`fifo_size_lg-1):0

`define fifo_high_addr (`fifo_size_lg-1):(`fifo_size_lg>>1)
`define fifo_low_addr ((`fifo_size_lg>>1)-1):0

// Fifo using declared registers for storage.

module fifo(dout,empty,full,ready,op,din,clk);
   input op, din, clk;
   output dout, empty, full, ready;
   // Note: Clock ignored.

   wire [31:0] dout;
   reg         empty,full;
   wire        ready;
   wire [1:0]  op;
   wire [31:0] din;

   parameter op_nop = 0;
   parameter op_insert = 1;
   parameter op_remove = 2;
   parameter op_reset = 3;

   reg [31:0] fifo_mem [0:`fifo_size-1];

   reg [`fifo_addr_bits] head;             // Head of queue.
   reg [`fifo_addr_bits] tail;             // Next empty place to be filled.

   assign                ready = op === op_nop;
   assign                dout = fifo_mem[head];     

   always @( op ) 
     case ( op )
       op_nop:;
       op_insert: if( !full ) begin
          fifo_mem[tail] = din; tail = tail + 1;
          full = head === tail;
          empty = 0;
       end
       op_remove: if( !empty ) begin 
          head = head + 1;
          full = 0;
          empty = head === tail;
       end
       op_reset: begin head = 0; tail = 0; empty = 1; full = 0; end
     endcase // case( op )

endmodule // fifo

// Fifo using (model of) standard memory chip for storage.

module fifom(dout,empty,full,ready,op,din,clk);
   input op, din, clk;
   output dout, empty, full, ready;

   reg [31:0] dout;
   reg        empty, full, ready;
   wire [1:0] op;
   wire [31:0] din;
   
   reg [31:0]  dbuffer;

   parameter op_nop = 0;
   parameter op_insert = 1;
   parameter op_remove = 2;
   parameter op_reset = 3;

   tri [31:0] dq;
   reg        ras, cas, we, oe;
   reg [4:0]  addr;
   reg        write;

/*  Emacs Common Lisp routine generating instantiations.
 (loop for i from 31 downto 3 by 4
      do (insert (format "memchip2 fifo_mem%d(dq[%d:%d], ras, cas, addr, we, oe);\n"
                      (/ i 4) i (- i 3))))  */

   memchip fifo_mem7(dq[31:28], ras, cas, addr, we, oe);
   memchip fifo_mem6(dq[27:24], ras, cas, addr, we, oe);
   memchip fifo_mem5(dq[23:20], ras, cas, addr, we, oe);
   memchip fifo_mem4(dq[19:16], ras, cas, addr, we, oe);
   memchip fifo_mem3(dq[15:12], ras, cas, addr, we, oe);
   memchip fifo_mem2(dq[11:8], ras, cas, addr, we, oe);
   memchip fifo_mem1(dq[7:4], ras, cas, addr, we, oe);
   memchip fifo_mem0(dq[3:0], ras, cas, addr, we, oe);

   assign     dq = write ? dbuffer : 32'bz;
   
   reg [`fifo_addr_bits] head;             // Head of queue.
   reg [`fifo_addr_bits] tail;             // Next empty place to be filled.

   always 
     begin
        wait( op === op_nop ) ready = 1;

        @( op ) begin
           
           ready = 0; dbuffer = din;

           case ( op )
             op_nop: begin $display("Unexpected nop."); $stop; end

             op_insert: if( !full ) begin
                @(posedge clk);
                addr = tail[`fifo_high_addr];
                ras = 0;
                @(posedge clk); 
                addr = tail[`fifo_low_addr];
                cas = 0; write = 1; we = 0;
                @(posedge clk);  
                ras = 1; cas = 1; write = 0; we = 1;
                if( empty ) dout = dbuffer;
                tail = tail + 1;
                full = head === tail;
                empty = 0;
             end // if ( !full )
             
             op_remove: if( !empty ) begin
                head = head + 1;
                @(posedge clk);
                addr = head[`fifo_high_addr];
                ras = 0;
                @(posedge clk);
                addr = head[`fifo_low_addr];
                cas = 0; oe = 0;
                @(posedge clk);   
                dout = dq; ras = 1; cas = 1; oe = 1;
                full = 0;
                empty = head === tail;
             end // if ( !empty )

             op_reset: begin
                head = 0; tail = 0; empty = 1; full = 0; dout = 0;
                ras = 1; cas = 1; write = 0; oe = 1;  we = 1;
             end
           endcase // case( op )
        end // @ ( op )
     end // always begin
   

endmodule // fifo

// Testbench for fifo.

module test_fifo();

   wire [31:0] dout;
   wire        empty, full;
   reg [1:0]   op;
   wire [31:0]  din;
   reg          clk;
   wire         ready;

   fifo f1(dout,empty,full,ready,op,din,clk);

   function integer ctoval;
      input [31:0] c;
      ctoval = c * 3 + 1;
   endfunction // ctoval

   integer         errors;
   task estop;
      input [400:0] msg;
      begin
         errors = errors + 1;
         $display("Error %d: %s\n",errors,msg);
         $stop;
      end
   endtask // estop

   task fifo_command;
      input [1:0] command;
      begin
         wait( ready ) op = command;
         wait( !ready ) op = f1.op_nop;
         wait( ready );
      end
   endtask // fifo_command
   

   integer dini;
   assign din = ctoval(dini);

   initial begin:I

      integer i, inside, tail_c, head_c;

      errors = 0;
      clk = 0;

      op = f1.op_nop; 
      wait( ready ) op = f1.op_reset;
      wait( !ready ) op = f1.op_nop;
      
      op = f1.op_reset; #1 op = f1.op_nop; #1;

      // Fill

      if( !empty || full ) estop("Before fill, should be empty.");

      for( dini = 0; dini < `fifo_size; dini = dini + 1 ) begin
         if( full ) estop("Fill, shouldn't be full.");
         #1;
         fifo_command( f1.op_insert );
         if( dout!==ctoval(0) ) estop("Fill, expecting first input at head.");
      end

      if( !full || empty ) estop("After fill, should be full.");

      // Try to overfill
      
      for( dini = `fifo_size; dini < `fifo_size+10; dini = dini + 1 ) begin
         if( !full || empty ) estop("Overfill, should be full.");
         #1 fifo_command( f1.op_insert );
         if( dout!==ctoval(0) )
           estop("Overfill, expecting first input at head.");
      end
 
      // Drain

      for( dini = 0; dini < `fifo_size; dini = dini + 1 ) begin
         if( empty ) estop("Drain, shouldn't be empty.");
         if( dout!==ctoval(dini) )
           estop("Drain, expecting previous input at head.");
         #1 fifo_command( f1.op_remove );
      end

      if( !empty || full ) estop("After drain, should be empty.");

      // Fill partway

      for( dini = `fifo_size; dini < `fifo_size+10; dini = dini + 1 ) begin
         #1 fifo_command( f1.op_insert );
         if( dout!==ctoval(`fifo_size) )
           estop("Fill partway, expecting first input at head.");
      end
 
      // Drain

      for( dini = `fifo_size; dini < `fifo_size+10; dini = dini + 1 ) begin
         if( empty ) estop("Drain, shouldn't be empty.");
         if( dout!==ctoval(dini) )
           estop("Drain, expecting previous input at head.");
         #1 fifo_command( f1.op_remove );
      end

      // Random;

      tail_c = dini;
      head_c = tail_c;
      
      for( i=0; i<1000; i=i+1 ) begin
         case( $random & 1 )
           0: begin
              #1 fifo_command( f1.op_remove );
              if( head_c !== tail_c ) head_c = head_c + 1;
           end
           1: begin
              dini = tail_c;
              if( !full ) tail_c = tail_c + 1;
              #1 fifo_command( f1.op_insert );
           end
         endcase

         if( head_c === tail_c ) begin
            if( !empty || full ) estop("Random, expected to be empty.");
         end else begin
            if( dout !== ctoval(head_c) ) estop("Random, unexpected value.");
         end
         if( tail_c - head_c === `fifo_size &&
             ( !full || empty ) ) estop("Random, expected to be full.");

      end // for ( i=0; i<1000; i=i+1 )

      $display("Done testing.");
      $stop;
      
   end // block: I

   always #30 clk = ~clk;

   
endmodule // test_fifo

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -