fifo.v.txt
上传用户:saul_905
上传日期:2013-11-27
资源大小:184k
文件大小:6k
源码类别:

VHDL/FPGA/Verilog

开发平台:

Visual C++

  1. // Synchronous FIFO.  4 x 16 bit words.
  2. //
  3. module fifo (clk, rstp, din, writep, readp, dout, emptyp, fullp);
  4. input clk;
  5. input rstp;
  6. input [15:0] din;
  7. input readp;
  8. input writep;
  9. output [15:0] dout;
  10. output emptyp;
  11. output fullp;
  12. // Defines sizes in terms of bits.
  13. //
  14. parameter DEPTH = 2, // 2 bits, e.g. 4 words in the FIFO.
  15. MAX_COUNT = 2'b11; // topmost address in FIFO.
  16. reg  emptyp;
  17. reg fullp;
  18. // Registered output.
  19. reg [15:0] dout;
  20. // Define the FIFO pointers.  A FIFO is essentially a circular queue.
  21. //
  22. reg [(DEPTH-1):0] tail;
  23. reg [(DEPTH-1):0] head;
  24. // Define the FIFO counter.  Counts the number of entries in the FIFO which
  25. // is how we figure out things like Empty and Full.
  26. //
  27. reg [(DEPTH-1):0] count;
  28. // Define our regsiter bank.  This is actually synthesizable!
  29. //
  30. reg [15:0] fifomem[0:MAX_COUNT];
  31. // Dout is registered and gets the value that tail points to RIGHT NOW.
  32. //
  33. always @(posedge clk) begin
  34.    if (rstp == 1) begin
  35.       dout <= 16'h0000;
  36.    end
  37.    else begin
  38.       dout <= fifomem[tail];
  39.    end
  40. end 
  41.      
  42. // Update FIFO memory.
  43. always @(posedge clk) begin
  44.    if (rstp == 1'b0 && writep == 1'b1 && fullp == 1'b0) begin
  45.       fifomem[head] <= din;
  46.    end
  47. end
  48.                   
  49. // Update the head register.
  50. //
  51. always @(posedge clk) begin
  52.    if (rstp == 1'b1) begin
  53.       head <= 2'b00;
  54.    end
  55.    else begin
  56.       if (writep == 1'b1 && fullp == 1'b0) begin
  57.          // WRITE
  58.          head <= head + 1;
  59.       end
  60.    end
  61. end
  62. // Update the tail register.
  63. //
  64. always @(posedge clk) begin
  65.    if (rstp == 1'b1) begin
  66.       tail <= 2'b00;
  67.    end
  68.    else begin
  69.       if (readp == 1'b1 && emptyp == 1'b0) begin
  70.          // READ               
  71.          tail <= tail + 1;
  72.       end
  73.    end
  74. end
  75. // Update the count regsiter.
  76. //
  77. always @(posedge clk) begin
  78.    if (rstp == 1'b1) begin
  79.       count <= 2'b00;
  80.    end
  81.    else begin
  82.       case ({readp, writep})
  83.          2'b00: count <= count;
  84.          2'b01: 
  85.             // WRITE
  86.             if (count != MAX_COUNT) 
  87.                count <= count + 1;
  88.          2'b10: 
  89.             // READ
  90.             if (count != 2'b00)
  91.                count <= count - 1;
  92.          2'b11:
  93.             // Concurrent read and write.. no change in count
  94.             count <= count;
  95.       endcase
  96.    end
  97. end
  98.          
  99. // *** Update the flags
  100. //
  101. // First, update the empty flag.
  102. //
  103. always @(count) begin
  104.    if (count == 2'b00)
  105.       emptyp <= 1'b1;
  106.    else
  107.       emptyp <= 1'b0;
  108. end
  109. // Update the full flag
  110. //
  111. always @(count) begin
  112.    if (count == MAX_COUNT)
  113.       fullp <= 1'b1;
  114.    else
  115.       fullp <= 1'b0;
  116. end
  117. endmodule
  118. // synopsys translate_off
  119. `define TEST_FIFO
  120. // synopsys translate_off
  121. `ifdef TEST_FIFO
  122. module test_fifo;
  123. reg clk;
  124. reg rstp;
  125. reg [15:0] din;
  126. reg readp;
  127. reg writep;
  128. wire [15:0] dout;
  129. wire emptyp;
  130. wire fullp;
  131. reg [15:0] value;
  132. fifo U1 (
  133.    .clk (clk),
  134.    .rstp (rstp),
  135.    .din (din),
  136.    .readp (readp),
  137.    .writep (writep),
  138.    .dout (dout),
  139.    .emptyp (emptyp),
  140.    .fullp (fullp)
  141. );
  142. task read_word;
  143. begin
  144.    @(negedge clk);
  145.    readp = 1;
  146.    @(posedge clk) #5;
  147.    $display ("Read %0h from FIFO", dout);
  148.    readp = 0;
  149. end
  150. endtask
  151.    
  152. task write_word;
  153. input [15:0] value;
  154. begin
  155.    @(negedge clk);
  156.    din = value;
  157.    writep = 1;
  158.    @(posedge clk);
  159.    $display ("Write %0h to FIFO", din);
  160.    #5;
  161.    din = 16'hzzzz;
  162.    writep = 0;
  163. end
  164. endtask
  165. initial begin
  166.    clk = 0;
  167.    forever begin
  168.       #10 clk = 1;
  169.       #10 clk = 0;
  170.    end
  171. end
  172. initial begin
  173.    $shm_open ("./fifo.shm");
  174.    $shm_probe (test_fifo, "AS");
  175.    
  176.    //test1;
  177.    test2;
  178.    
  179.    $shm_close;
  180.    $finish;
  181. end
  182. task test1;
  183. begin
  184.    din = 16'hzzzz;
  185.    writep = 0;
  186.    readp = 0;
  187.    // Reset
  188.    rstp = 1;
  189.    #50;
  190.    rstp = 0;
  191.    #50;
  192.    
  193.    // ** Write 3 values.
  194.    write_word (16'h1111);
  195.    write_word (16'h2222);
  196.    write_word (16'h3333);
  197.    
  198.    // ** Read 2 values
  199.    read_word;
  200.    read_word;
  201.    
  202.    // ** Write one more
  203.    write_word (16'h4444);
  204.    
  205.    // ** Read a bunch of values
  206.    repeat (6) begin
  207.       read_word;
  208.    end
  209.    
  210.    // *** Write a bunch more values
  211.    write_word (16'h0001);
  212.    write_word (16'h0002);
  213.    write_word (16'h0003);
  214.    write_word (16'h0004);
  215.    write_word (16'h0005);
  216.    write_word (16'h0006);
  217.    write_word (16'h0007);
  218.    write_word (16'h0008);
  219.    // ** Read a bunch of values
  220.    repeat (6) begin
  221.       read_word;
  222.    end
  223.    
  224.    $display ("Done TEST1.");
  225. end
  226. endtask
  227. // TEST2
  228. //
  229. // This test will operate the FIFO in an orderly manner the way it normally works.
  230. // 2 threads are forked; a reader and a writer.  The writer writes a counter to
  231. // the FIFO and obeys the fullp flag and delays randomly.  The reader likewise
  232. // obeys the emptyp flag and reads at random intervals.  The result should be that
  233. // the reader reads the incrementing counter out of the FIFO.  The empty/full flags
  234. // should bounce around depending on the random delays.  The writer repeats some
  235. // fixed number of times and then terminates both threads and kills the sim.
  236. //
  237. task test2;
  238. reg [15:0] writer_counter;
  239. begin
  240.    writer_counter = 16'h0001;
  241.    din = 16'hzzzz;
  242.    writep = 0;
  243.    readp = 0;
  244.    // Reset
  245.    rstp = 1;
  246.    #50;
  247.    rstp = 0;
  248.    #50;
  249.    
  250.    fork
  251.       // Writer
  252.       begin
  253.          repeat (500) begin
  254.             @(negedge clk);
  255.             if (fullp == 1'b0) begin
  256.                write_word (writer_counter);
  257.                #5;
  258.                writer_counter = writer_counter + 1;
  259.             end
  260.             else begin
  261.                $display ("WRITER is waiting..");
  262.             end
  263.             // Delay a random amount of time between 0ns and 100ns
  264.             #(50 + ($random % 50));
  265.          end
  266.          $display ("Done with WRITER fork..");
  267.          $finish;
  268.       end
  269.       
  270.       // Reader
  271.       begin
  272.          forever begin
  273.             @(negedge clk);
  274.             if (emptyp == 1'b0) begin
  275.                read_word;
  276.             end  
  277.             else begin
  278.                $display ("READER is waiting..");
  279.             end
  280.             // Delay a random amount of time between 0ns and 100ns
  281.             #(50 + ($random % 50));
  282.          end
  283.       end
  284.    join
  285. end
  286. endtask
  287. always @(fullp)
  288.    $display ("fullp = %0b", fullp);
  289.    
  290. always @(emptyp)
  291.    $display ("emptyp = %0b", emptyp);
  292. always @(U1.head)
  293.    $display ("head = %0h", U1.head);
  294. always @(U1.tail)
  295.    $display ("tail = %0h", U1.tail);
  296. endmodule
  297. `endif