已解决
【【萌新的FPGA学习之同步FIFO的代码与tb】】
来自网友在路上 180880提问 提问时间:2023-10-27 15:25:48阅读次数: 80
最佳答案 问答题库808位专家为你答疑解惑
萌新的FPGA学习之同步FIFO的代码与tb
对于FIFO的介绍在上一节
在这里主要介绍要用如何的判断方法使得FIFO 确定空满
空满信号产生
为产生 FIFO 空满标志,引入 cnt 计数器,cnt 计数器用于指示 FIFO 内部存储数据
个数。
(1)当只有写操作时,cnt 加 1;只有读操作是,cnt 减 1;其他情况下,cnt 保持;
(2)当 cnt 为 0 时,说明 FIFO 为空,empty 置位;
(3)当 cnt 等于 FIFO 深度时,说明 FIFO 已满,full 置位
下面附上同步 FIFO的代码
//synchronous fifo
module FIFO_syn #(parameter WIDTH = 16, // the fifo wideparameter DEPTH = 1024, // deepthparameter ADDR_WIDTH = clogb2(DEPTH), // bit wideparameter PROG_EMPTY = 100, // this what we set to emptyparameter PROG_FULL = 800 // this what we set to full)(input sys_clk ,input sys_rst ,input wr_en ,input rd_en ,input [WIDTH-1: 0] din ,output reg full ,output reg empty , /// 1 is real empty 0 is no emptyoutput reg prog_full ,output reg prog_empty ,output reg [WIDTH-1:0] dout );//========================================================================================//// define parameter and internal signals ////======================================================================================//reg [WIDTH-1 : 0] ram[DEPTH-1 : 0] ; // this we set a 15:0 total 1024 number ramreg [ADDR_WIDTH-1 : 0] wr_addr ; // this is write pointerreg [ADDR_WIDTH-1 : 0] rd_addr ; // this is read pointerreg [ADDR_WIDTH-1 : 0] fifo_cnt ;//=========================================================================================//// next is main code ////=========================================================================================//// we set a function let me to count the numberfunction integer clogb2; // remember integer has symbol reg has no symbolinput[31:0]value;beginvalue=value-1;for(clogb2=0;value>0;clogb2=clogb2+1)value=value>>1;endendfunction// this you can see from the PPT 5-74//=================================================== next is used to readalways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst)rd_addr <= {ADDR_WIDTH{1'b0}};else if(rd_en && !empty)beginrd_addr <= rd_addr+1'd1;dout <= ram[rd_addr];endelsebeginrd_addr <= rd_addr;dout <= dout;endend//=================================================== next is used to writealways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst == 1)beginwr_addr <= {ADDR_WIDTH{1'b0}} ; // this let pointer to zeroendelse if( wr_en && !full )begin // no full and wr_en and whether to write prog_full therewr_addr <= wr_addr + 1'b1 ;ram[wr_addr] <= din ;endelsewr_addr <= wr_addr ;end//============================================================== next is used to set fifo_cntalways@(posedge sys_clk or posedge sys_rst )beginif(sys_rst)beginfifo_cnt <= {ADDR_WIDTH{1'b0}};endelse if(wr_en && !full && !rd_en)beginfifo_cnt <= fifo_cnt + 1'b1 ;endelse if(rd_en && !empty && !wr_en)beginfifo_cnt <= fifo_cnt - 1'b1 ;endelsefifo_cnt <= fifo_cnt ;end//========================================================== next is empty// we set counter so when the count is zero emptyalways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst == 1)beginempty <= 1'b1 ; // begin we set empty to highend// there is two possibilties first no write fifo_cnt is all zero//second is no write it will be change to zero is just a will empty signalelseempty <= (!wr_en && (fifo_cnt[ADDR_WIDTH-1:1] == 'b0))&&((fifo_cnt[0] == 1'b0) || rd_en);end//============================================================ next is fullalways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst)full <= 1'b1;//reset:1elsefull <= (!rd_en && (fifo_cnt[ADDR_WIDTH-1:1]=={(ADDR_WIDTH-1){1'b1}})) && ((fifo_cnt[0] == 1'b1) || wr_en);end//============================================================ next is prog_full//prog_fullalways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst)prog_full<= 1'b1;//reset:1else if(fifo_cnt > PROG_FULL)prog_full<= 1'b1;elseprog_full<= 1'b0;end//prog_emptyalways@(posedge sys_clk or posedge sys_rst)beginif(sys_rst)prog_empty<=1'b1;//reset:1else if(fifo_cnt < PROG_EMPTY)prog_empty<=1'b1;elseprog_empty<=1'b0;end
endmodule
tb
```dart
`timescale 1ns/1ns
module tb;
parameter WIDTH = 16 ;
parameter DEPTH = 512 ;
parameter ADDR_WIDTH = 9 ;
parameter PROG_EMPTY = 100 ;
parameter PROG_FULL = 400 ;
reg sys_clk ;
reg sys_rst ;
reg [WIDTH-1:0] din ;
reg wr_en ;
reg rd_en ;
reg [11:0] cnt ;
wire [WIDTH-1:0] dout ;
wire full ;
wire empty ;
wire prog_full ;
wire prog_empty ;initial beginsys_clk = 0;sys_rst = 1;#100sys_rst = 0;
end
always #5 sys_clk = ~sys_clk;always @ (posedge sys_clk or posedge sys_rst)beginif(sys_rst)cnt <= 'b0;elsecnt <= cnt + 1'd1;
endalways @ (posedge sys_clk or posedge sys_rst)beginif(sys_rst)beginwr_en <= 1'b0;rd_en <= 1'b0;din <= 16'b0;endelse if(cnt >= 'd10 && cnt <= DEPTH + 'd40)beginwr_en <= 1'b1;rd_en <= 1'b0;din <= din + 1'd1;endelse if((cnt >= 'd100 + DEPTH) && (cnt <= 2*DEPTH + 'd140))beginwr_en <= 1'b0;rd_en <= 1'b1;din <= 'b0;endelse beginwr_en <= 1'b0;rd_en <= 1'b0;din <= 'b0;end
endFIFO_syn#(.WIDTH ( WIDTH ),.DEPTH ( DEPTH ),.ADDR_WIDTH ( ADDR_WIDTH ),.PROG_EMPTY ( PROG_EMPTY ),.PROG_FULL ( PROG_FULL )
)u_FIFO_syn(.sys_clk ( sys_clk ),.sys_rst ( sys_rst ),.wr_en ( wr_en ),.rd_en ( rd_en ),.din ( din ),.full ( full ),.empty ( empty ),.prog_full ( prog_full ),.prog_empty ( prog_empty ),.dout ( dout ));endmodule
查看全文
99%的人还看了
相似问题
- JVM——运行时数据区(程序计数器+栈)
- 实验(三):微程序计数器uPC实验
- 【FPGA】Verilog:升降计数器 | 波纹计数器 | 约翰逊计数器 | 实现 4-bit 升降计数器的 UP/DOWN
- CSS 下拉菜单、提示工具、图片廊、计数器
- 【数字电路与逻辑设计实验】——Multisim仿真实验-xx进制的计数器
- 深入理解JVM虚拟机第十三篇:详解JVM中的程序计数器
- React函数式写法和类式写法的区别(以一个计数器功能为例子)
- 对于使用win32 API获取性能计数器的理解
- 【Verilog语法】比较不同计数器的运算方式,其中有一个数是延迟打一拍的效果,目的是使得两个计数器的结果相同。
- 「干货」洁净室悬浮粒子计数器全部常见型号参数汇总
猜你感兴趣
版权申明
本文"【【萌新的FPGA学习之同步FIFO的代码与tb】】":http://eshow365.cn/6-26134-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!