基于verilog的不同位宽的同步FIFO设计
工具 quartus13.1
仿真工具modelsimse10.4
参考了两位博主的文章
Mr.zhang_FPGA:
基于verilog的同步FIFO设计,
emperor_strange: FIFO读写侧位数不同的处理
一、同步fifo,读写侧位数不同设计
1、FIFO设计难点及主要参数:
主要参数:fifo深度,fifo宽度,空标志,满状态。
同步FIFO设计难点在于判断FIFO的满状态和空状态。
判断空状态:
我们使用一个count计数器,在读状态时:count来一个时钟减一,计数到0,则为空
判断满状态:
在读状态时:count来一个时钟加一,计数到MAX(MAX为FIFO深度-1),则为满
对于不同位宽的同步FIFO设计
即读写两次分别进行控制,要么设置FIFO宽度与写侧相同,在读侧进行控制;要么设置FIFO宽度与读侧相同,在写侧进行控制。我们在让FIFO宽度和读侧相同,在写侧进行控制。
自己是在上面两位博主上面自己改的,所以直接开源了。
直接上代码:
`timescale 1ns / 1ns
1 module snfifo4(
2 input clk,
3 input rst_n,
4 input [15:0] din,
5 input din_vld,
6 input read,
7
8 output[7:0] data_out,
9 output full,
10 output emty
11 );
12
13 reg [7:0] data_in;
14 reg [7:0] fifo_reg[7:0];//深度为8
15 reg [2:0] w_head,R_tail;
16 reg [2:0] count;
17 reg [7:0] dout;
18 reg f,e;
19
20 reg wr_en;
21
22
23 wire add_cnt;
24 wire end_cnt;
25 reg [1:0] cnt;
26
27 parameter MAX = 7;
28
29 //FIFO宽度与读侧相同
30 //在写侧用一个计数器来控制
31 //din[7:0] ,dout[4:0]
32
33 assign add_cnt = din_vld ;
34 assign end_cnt = add_cnt && cnt == 2-1;
35
36 always @(posedge clk or negedge rst_n)begin
37 if(rst_n==0)begin
38 cnt <= 0;
39 end
40 else if(add_cnt)begin
41 if(end_cnt)begin
42 cnt <= 0;
43 end
44 else
45 cnt <= cnt + 1'b1;
46 end
47 end
48
49 //注意写使能和写数据
50 always @(*)begin
51 if(add_cnt)
52 wr_en = 1;
53 else
54 wr_en = 0;
55 end
56
57 always @(posedge clk or negedge rst_n)begin
58 if(rst_n == 0)begin
59 data_in <= 0;
60 end
61 else if(add_cnt)begin
62 data_in <= din[15 -8*cnt -:8];
63 end
64 end
65
66 //更新写指针
67 always @ (posedge clk)
68 if(!rst_n)
69 w_head <= 3'd0;
70 else if(wr_en && !full)
71 w_head <= w_head + 1'b1;
72 else if(full) w_head <= 3'd0;
73 //更新读指针
74 always @ (posedge clk)
75 if(!rst_n)
76 R_tail <= 3'd0;
77 else if(read && !emty)
78 R_tail <= R_tail + 1'b1;
79 else if(emty) R_tail <= 3'd0;
80
81 //count计数器
82 always @(posedge clk)
83 if(!rst_n)
84 begin
85 count <= 3'd0;
86
87 end
88 else
89 case({read,wr_en})
90 2'b00:
91 count <= count;
92 2'b01:
93 if(count != MAX)
94 count <= count + 1'b1;
95 2'b10:
96 if(count != 0)
97 count <= count - 1'b1;
98 2'b11:
99 //;
100 count <= count;
101 endcase
102 //读数据
103 always @(posedge clk)
104 if(!rst_n)
105 dout <= 8'd0;
106 else if(read && !emty)
107 dout <= fifo_reg[R_tail];
108 ///写数据
109 always @(posedge clk)
110 if(wr_en && !full)
111 fifo_reg[w_head] <= data_in;
112
113 always @ (posedge clk)
114 if(count==0)
115 e <= 1'b1;
116 else e <= 1'b0;
117 always @ (posedge clk)
118 if(count==MAX)
119 f <= 1'b1;
120 else f <= 1'b0;
121 assign full = f;
122 assign emty = e;
123
124
125 assign data_out = dout;
126
127 endmodule
128
仿真测试文件需要自己下载,有能力的可以自己编写,测试文件还是比较简单的。
仿真文件下载连接:https://download.csdn.net/download/longyuzhang/12986849
仿真结果:
对于我这样的新手来说,改动代码还是比较吃力的,花了一个晚上弄这个。目前我自己分析,这个FIFO应该功能仿真时通过要求的。后仿真没有做,时序分析那一块我还没学。求FPGA大佬评论区指点指点。