15.同步FIFO实现代码
15.1. FIFO模块(FIFO_sync)
//synchronous FIFO
module FIFO_sync(clk,
rst_n,
w_en,
r_en,
w_data,
r_data,
count,
full,
empty
);
//parameter defines
parameter DATA_WIDTH = 8;
parameter FIFO_DEPTH = 8;
parameter ADDR_WIDTH = 3;
//signals direction declaration
input clk;
input rst_n;
input w_en;
input r_en;
input w_data;
output r_data;
output full;
output empty;
output count;
//register declaration
reg [ADDR_WIDTH-1:0] w_ptr;
reg [ADDR_WIDTH-1:0] r_ptr;
reg [DATA_WIDTH-1:0] r_data;
reg [ADDR_WIDTH:0] count;
reg [DATA_WIDTH-1:0] mem[0:FIFO_DEPTH-1];
integer i;
//write operation
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) w_ptr <= {ADDR_WIDTH{1'b0}};
else
begin
if(w_en && ~full)
begin
mem[w_ptr] <= w_data;
w_ptr <= w_ptr + 1'b1;
end
end
end
//read operation
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
r_data <= {DATA_WIDTH{1'b0}};
r_ptr <= {ADDR_WIDTH{1'b0}};
end
else
begin
if(r_en && ~empty)
begin
r_data <= mem[r_ptr];
r_ptr <= r_ptr + 1;
end
end
end
//count signal process
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) count <= {(ADDR_WIDTH+1){1'b0}};
else
begin
if(w_en && ~full && r_en && ~empty) count <= count;
else if(w_en && ~full) count <= count + 1'b1;
else if(r_en && ~empty) count <= count - 1'b1;
end
end
//mem initialization
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
for(i=0;i<FIFO_DEPTH;i=i+1) mem[i] <= {DATA_WIDTH{1'b0}};
end
end
//empty and full signal process
assign empty = (count == 0);
assign full = (count == {ADDR_WIDTH{1'b1}} + 1);
endmodule
信号列表:
系统信号:
clk
:系统时钟
rst_n
:复位信号
输入:
w_en
:写使能
r_en
:读使能
w_data
:写入FIFO数据(外部输入,线网类型)
输出:
r_data
:读出FIFO数据(输出缓存,reg类型)
full
:FIFO满信号
empty
:FIFO空信号
count
:FIFO数据数量
寄存器:
w_ptr
:写指针
r_ptr
:读指针
mem
:FIFO存储空间
参数定义:
DATA_WIDTH
:数据位宽(FIFO中存储的数据比特位数)
FIFO_DEPTH
:FIFO深度(容量)
ADDR_WIDTH
:地址位宽(log2FIFO_DEPTH
)
内部逻辑分为四部分:写操作,读操作,count处理模块,men初始化
写操作
:复位场景下w_ptr
复位(清0);满足写条件时,数据写入mem[w_ptr]
,写指针+1;
读操作
:复位场景下r_data
,r_ptr
复位(清0);满足读条件时,数据从mem[r_ptr]
读到r_data
,读指针+1;
count
:复位场景下count
清0;同时读写count
不变,只写时count
自增1,只读时count
自减1。
mem
:复位场景,内存块清0。
最后添加empty
,full
判断逻辑。
15.2. 测试模块(FIFO_sync_top)
//test file of FIFO_syno
module FIFO_sync_top;
reg clk;
reg rst_n;
reg w_en;
reg r_en;
reg [7:0] w_data;
reg [3:0] count;
reg [7:0] r_data;
wire full;
wire empty;
initial begin
clk = 0;
rst_n = 0;
w_data = 8'b0000_0000;
w_en = 0;
r_en = 0;
#25 rst_n = 1;
#50 rst_n = 0;
#100 rst_n = 1;
#25 w_en = 1;
#100 r_en = 1;
#100 w_en = 0; r_en = 0;
#100 w_en = 1;
#1200 r_en = 1; w_en = 0;
end
initial begin
for(int i = 0; i < 50; i = i + 1) begin
#100 w_data = i;
end
end
//generate system clock
always begin
#50 clk = ~clk;
end
//finish simulation
initial
begin
#4000
$stop();
end
//instance FIFO_sync module
FIFO_sync ut(
.clk(clk),
.rst_n(rst_n),
.w_data(w_data),
.r_data(r_data),
.w_en(w_en),
.r_en(r_en),
.count(count),
.full(full),
.empty(empty)
);
endmodule
定义信号
输入FIFO(激励):clk,rst,w_en,r_en,w_data
接收FIFO输出:count,r_data
两个initial块
:产生激励。
always块
:产生系统时钟信号。
实例化FIFO_sync并连接相应信号线。
3.波形分析
编译命令:
vcs FIFO_sync_test.sv FIFO_sync.v -sverilog -debug_all
仿真命令:
./simv -gui
波形:
波形分析:
0~250 系统复位
250~ 写入第一个数据
350 同时读写,写入02,读出数据为01----------------------------------------------------(同时读写)
450 不读写,count不变为1------------------------------------------------------------------(不读不写)
550-1150 持续写入数据,1150时刻count为8,FIFO为满 full信号拉高-----------(不读只写入)
1150~1650 FIFO为满,此区间w_en为高,r_en为低,数据无法写入------------------------(写边界)
1700 时刻w_en拉底,r_拉高进行读操作
1750~2450 数据持续读出,2450时刻FIFO为空,empty拉高------------------------------(不写只读出)
2550~ w_en为低,r_en为高,empty为高,无法读出数据-----------------------------(读边界)
参考文献:
https://zhuanlan.zhihu.com/p/404518524