输入变量:时钟、复位、输入数据、写使能、读使能。
输出变量:空信号、满信号、将空信号、将满信号、输出数据、FIFO计数器、FWFT模式下输出数据。
FWFT模式是读信号和读出数据同时发生。
总体思路:确定FIFO的所存储数据的个位以及位宽,定义一个读写有效信号,对将满将空信号进行判断,以及空信号、满信号的判断,根据读写使能信号、空满信号状态,以及FIFO计数器计数,来观察当前FIFO存储量。
本次编写的同步FIFO的数据位宽是16位,深度是8。
module fifo#.(parameter aw=8,//深度
parameter dw=16//数据位宽
)
(
input clk,rst,
input [dw-1:0]din,
input wr,rd,
output reg [aw:0]fifo_cnt,
output reg [dw-1:0]dout,
output [dw-1:0]fwft_dout,
output reg full,empty,
output almost_full,almost_empty
);
parameter max_fifo_len=(1<<aw);
parameter almost_full_len=max_fifo_len-8;
parameter almost_empty_len=8;
reg[dw-1:0]buff[0:max_fifo_len-1];
reg[aw-1:0]wr_cnt,rd_cnt;
wire valid_wr=(wr&(~full));
wire valid_rd=(rd&(~empty));
//读写有效判断
assign almost_full=(fifo_cnt>almost_full_len);
assign almost_empty=(fifo_cnt<almost_empty_len);
//将满将空状态判断
always@(*) full<=(fifo_cnt==max_fifo_len-2);
always@(*) empty<=fifo_cnt==0;
//满空状态判断
always@(posedge clk)
casex({rst,valid_wr,valid_rd})
3'd1xx:fifo_cnt<=0;
3'd010:fifo_cnt<=fifo_cnt+1;
3'd001:fifo_cnt<=fifo_cnt-1;
3'd000,3'd011:fifo_cnt<=fifo_cnt;
endcase
//fifo计数器加减控制
always@(posedge clk) if(rst) wr_cnt<=0;else if(valid_wr) wr_cnt<=wr_cnt+1;
always@(posedge clk) if(rst) rd_cnt<=0;else if(valid_rd) rd_cnt<=rd_cnt+1;
//读写计数器控制
always@(posedge clk)
if(valid_wr) buff[wr_cnt]<=din;
always@(posedge clk)
if(valid_rd) dout<=buff[rd_cnt];
//数据缓冲
assign fwft_dout=buff[rd_cnt];
//fwft模式下数据输出方式
endmodule
学习总结:
1. #.(parameter )属于在模块外部定义常量,而parameter是内部定义常量。
2.定义wire型变量直接赋值后,该变量不可再通过assign进行连续赋值。
3.对于fifo计数器计数范围0~256,是为了显示存入的数据量,读写计数器计数范围0~255,是因为用作指针,来指向数据缓冲器中对应位置的数据。
4.casex()语句与case()语句的区别在于对于x表示不在乎,{}符号用来拼接数据用也可以用来打拍用。
5.对于空满信号的判断,运用组合逻辑,只要有变量变化,就直接可以进行判断。