FPGA/Verilog HDL/AC620零基础入门学习——8*8同步FIFO实验
实验要求
该项目主要实现一个深度为8、位宽为8bit的同步FIFO存储单元。模块功能应包括读控制、写控制、同时读写控制、FIFO满状态、FIFO空状态等逻辑部分。
该项目由一个功能模块和一个testbench组成。其中功能模块的端口信号如下表所示。
提示:
(1)设定一个写地址waddr[2:0],每来一个写使能wr,则写地址加一;
(2)设定一个读地址raddr[2:0],每来一个读使能rd,则读地址加一;
(3)若同时读写,则读写地址不变,只是将输入数据din直接赋值给dout;
(4)FIFO中数据的个数cout=waddr-raddr;
(5)状态指示:
- 当cout=8时,FIFO满(full=1);
- 当cout=6时,FIFO快满了(almost_full=1);
- 当cout=4时,FIFO半满(半空)(half=1);
- 当cout=2时,FIFO快空了(almost_empty=1);
- 当cout=0时,FIFO空(empty=1);
sfifo
module sfifo(
clk,
rst_n,
data_in,
wr,
rd,
full,
empty,
data_out,
sfifo_cnt,
half,
almost_empty,
almost_full);
input clk;
input rst_n;
input [7:0] data_in;
input wr;
input rd;
output full;
output empty;
output almost_full;
output almost_empty;
output half;
output [7:0] data_out;
output [3:0] sfifo_cnt;
wire clk;
wire rst_n;
wire [7:0] data_in;
wire wr;
wire rd;
wire full;
wire empty;
wire almost_full;
wire almost_empty;
wire half;
reg [7:0] data_out;
reg [3:0] sfifo_cnt;
`define DEL 1 // Clock-to-output delay
reg [7:0] sfifo_ram[0:7]; // sfifo_ram initialized
reg [2:0] rd_ptr; // Read pointer
reg [2:0] wr_ptr; // Write pointer
assign empty = ( sfifo_cnt == 0 ) ? 1 : 0; //Empty signal
assign full = ( sfifo_cnt == 8 ) ? 1 : 0; //Full signal
assign almost_full = ( sfifo_cnt == 6 ) ? 1 : 0; //Almost Full signal
assign almost_empty = ( sfifo_cnt == 2 ) ? 1 : 0;//Almost Empty signal
assign half = ( sfifo_cnt == 4 ) ? 1 : 0;//HALF signal
// sfifo_cnt changed
// 当读有效, cnt--
// 当写有效, cnt++
always @( posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
sfifo_cnt <= #`DEL 4'h0;
end
else if( rd && ~wr ) begin
sfifo_cnt <= #`DEL sfifo_cnt - 1;
end
else if( ~rd && wr ) begin
sfifo_cnt <= #`DEL sfifo_cnt + 1;
end
else begin
sfifo_cnt <= sfifo_cnt;
end
end
always @( posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
rd_ptr <= #`DEL 3'h0;
end
else if( rd ) begin
if( rd_ptr == 3'h7 ) begin
rd_ptr <= #`DEL 3'h0;
end
else begin
rd_ptr <= #`DEL rd_ptr +1;
end
end
else begin
rd_ptr <= rd_ptr;
end
end
always @( posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
wr_ptr <= #`DEL 3'h0;
end
else if( wr ) begin
if( wr_ptr == 3'h7 ) begin
wr_ptr <= #`DEL 3'h0;
end
else begin
wr_ptr <= #`DEL wr_ptr +1;
end
end
else begin
wr_ptr <= wr_ptr;
end
end
always @( posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
data_out <= #`DEL 8'h0;
end
else if( wr ) begin
sfifo_ram[wr_ptr] <= #`DEL data_in;
end
else if( rd ) begin
data_out <= #`DEL sfifo_ram[rd_ptr];
end
end
endmodule
sfifo_test
module sfifo_test();
reg clk;
reg rst_n;
reg [7:0] data_in;
reg wr;
reg rd;
wire full;
wire empty;
wire almost_full;
wire almost_empty;
wire half;
wire [7:0] data_out;
wire [3:0] sfifo_cnt;
initial begin
rst_n=1;
clk=0;
wr=0;
rd=0;
data_in=0;
#1 rst_n=0;
#5 rst_n=1;
#3 wr=1;
#5 rd=1;
#5 rd=0;
#5 wr=0;
#5 wr=1;
#10 rd=1;
#10 rd=0;
end
always begin
#5 clk=~clk;
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
data_in<=0;
wr<=0;
rd<=0;
end
else begin
data_in<=$random;
end
end
initial begin
$dumpfile ("F:/Robei/practice/prac_07_sfifo/sfifo_test.vcd");
$dumpvars;
#5000;
$stop;
end
//---Module instantiation---
sfifo sfifo1(
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.wr(wr),
.rd(rd),
.full(full),
.empty(empty),
.almost_full(almost_full),
.almost_empty(almost_empty),
.half(half),
.data_out(data_out),
.sfifo_cnt(sfifo_cnt)
);
endmodule