fifo.v.txt
上传用户:saul_905
上传日期:2013-11-27
资源大小:184k
文件大小:6k
- // Synchronous FIFO. 4 x 16 bit words.
- //
- module fifo (clk, rstp, din, writep, readp, dout, emptyp, fullp);
- input clk;
- input rstp;
- input [15:0] din;
- input readp;
- input writep;
- output [15:0] dout;
- output emptyp;
- output fullp;
- // Defines sizes in terms of bits.
- //
- parameter DEPTH = 2, // 2 bits, e.g. 4 words in the FIFO.
- MAX_COUNT = 2'b11; // topmost address in FIFO.
- reg emptyp;
- reg fullp;
- // Registered output.
- reg [15:0] dout;
- // Define the FIFO pointers. A FIFO is essentially a circular queue.
- //
- reg [(DEPTH-1):0] tail;
- reg [(DEPTH-1):0] head;
- // Define the FIFO counter. Counts the number of entries in the FIFO which
- // is how we figure out things like Empty and Full.
- //
- reg [(DEPTH-1):0] count;
- // Define our regsiter bank. This is actually synthesizable!
- //
- reg [15:0] fifomem[0:MAX_COUNT];
- // Dout is registered and gets the value that tail points to RIGHT NOW.
- //
- always @(posedge clk) begin
- if (rstp == 1) begin
- dout <= 16'h0000;
- end
- else begin
- dout <= fifomem[tail];
- end
- end
-
- // Update FIFO memory.
- always @(posedge clk) begin
- if (rstp == 1'b0 && writep == 1'b1 && fullp == 1'b0) begin
- fifomem[head] <= din;
- end
- end
-
- // Update the head register.
- //
- always @(posedge clk) begin
- if (rstp == 1'b1) begin
- head <= 2'b00;
- end
- else begin
- if (writep == 1'b1 && fullp == 1'b0) begin
- // WRITE
- head <= head + 1;
- end
- end
- end
- // Update the tail register.
- //
- always @(posedge clk) begin
- if (rstp == 1'b1) begin
- tail <= 2'b00;
- end
- else begin
- if (readp == 1'b1 && emptyp == 1'b0) begin
- // READ
- tail <= tail + 1;
- end
- end
- end
- // Update the count regsiter.
- //
- always @(posedge clk) begin
- if (rstp == 1'b1) begin
- count <= 2'b00;
- end
- else begin
- case ({readp, writep})
- 2'b00: count <= count;
- 2'b01:
- // WRITE
- if (count != MAX_COUNT)
- count <= count + 1;
- 2'b10:
- // READ
- if (count != 2'b00)
- count <= count - 1;
- 2'b11:
- // Concurrent read and write.. no change in count
- count <= count;
- endcase
- end
- end
-
- // *** Update the flags
- //
- // First, update the empty flag.
- //
- always @(count) begin
- if (count == 2'b00)
- emptyp <= 1'b1;
- else
- emptyp <= 1'b0;
- end
- // Update the full flag
- //
- always @(count) begin
- if (count == MAX_COUNT)
- fullp <= 1'b1;
- else
- fullp <= 1'b0;
- end
- endmodule
- // synopsys translate_off
- `define TEST_FIFO
- // synopsys translate_off
- `ifdef TEST_FIFO
- module test_fifo;
- reg clk;
- reg rstp;
- reg [15:0] din;
- reg readp;
- reg writep;
- wire [15:0] dout;
- wire emptyp;
- wire fullp;
- reg [15:0] value;
- fifo U1 (
- .clk (clk),
- .rstp (rstp),
- .din (din),
- .readp (readp),
- .writep (writep),
- .dout (dout),
- .emptyp (emptyp),
- .fullp (fullp)
- );
- task read_word;
- begin
- @(negedge clk);
- readp = 1;
- @(posedge clk) #5;
- $display ("Read %0h from FIFO", dout);
- readp = 0;
- end
- endtask
-
- task write_word;
- input [15:0] value;
- begin
- @(negedge clk);
- din = value;
- writep = 1;
- @(posedge clk);
- $display ("Write %0h to FIFO", din);
- #5;
- din = 16'hzzzz;
- writep = 0;
- end
- endtask
- initial begin
- clk = 0;
- forever begin
- #10 clk = 1;
- #10 clk = 0;
- end
- end
- initial begin
- $shm_open ("./fifo.shm");
- $shm_probe (test_fifo, "AS");
-
- //test1;
- test2;
-
- $shm_close;
- $finish;
- end
- task test1;
- begin
- din = 16'hzzzz;
- writep = 0;
- readp = 0;
- // Reset
- rstp = 1;
- #50;
- rstp = 0;
- #50;
-
- // ** Write 3 values.
- write_word (16'h1111);
- write_word (16'h2222);
- write_word (16'h3333);
-
- // ** Read 2 values
- read_word;
- read_word;
-
- // ** Write one more
- write_word (16'h4444);
-
- // ** Read a bunch of values
- repeat (6) begin
- read_word;
- end
-
- // *** Write a bunch more values
- write_word (16'h0001);
- write_word (16'h0002);
- write_word (16'h0003);
- write_word (16'h0004);
- write_word (16'h0005);
- write_word (16'h0006);
- write_word (16'h0007);
- write_word (16'h0008);
- // ** Read a bunch of values
- repeat (6) begin
- read_word;
- end
-
- $display ("Done TEST1.");
- end
- endtask
- // TEST2
- //
- // This test will operate the FIFO in an orderly manner the way it normally works.
- // 2 threads are forked; a reader and a writer. The writer writes a counter to
- // the FIFO and obeys the fullp flag and delays randomly. The reader likewise
- // obeys the emptyp flag and reads at random intervals. The result should be that
- // the reader reads the incrementing counter out of the FIFO. The empty/full flags
- // should bounce around depending on the random delays. The writer repeats some
- // fixed number of times and then terminates both threads and kills the sim.
- //
- task test2;
- reg [15:0] writer_counter;
- begin
- writer_counter = 16'h0001;
- din = 16'hzzzz;
- writep = 0;
- readp = 0;
- // Reset
- rstp = 1;
- #50;
- rstp = 0;
- #50;
-
- fork
- // Writer
- begin
- repeat (500) begin
- @(negedge clk);
- if (fullp == 1'b0) begin
- write_word (writer_counter);
- #5;
- writer_counter = writer_counter + 1;
- end
- else begin
- $display ("WRITER is waiting..");
- end
- // Delay a random amount of time between 0ns and 100ns
- #(50 + ($random % 50));
- end
- $display ("Done with WRITER fork..");
- $finish;
- end
-
- // Reader
- begin
- forever begin
- @(negedge clk);
- if (emptyp == 1'b0) begin
- read_word;
- end
- else begin
- $display ("READER is waiting..");
- end
- // Delay a random amount of time between 0ns and 100ns
- #(50 + ($random % 50));
- end
- end
- join
- end
- endtask
- always @(fullp)
- $display ("fullp = %0b", fullp);
-
- always @(emptyp)
- $display ("emptyp = %0b", emptyp);
- always @(U1.head)
- $display ("head = %0h", U1.head);
- always @(U1.tail)
- $display ("tail = %0h", U1.tail);
- endmodule
- `endif