(原创)同步FIFO的设计与技巧
本设计是同步FIFO,但我的ram使用了双端口的异步ram,
为什么要使用双端口呢?是不是太浪费资源了?
其实不然,之所以用双端口的ram,主要原因是同时进行读写数据时,两个端口互不影响,能同时进行,解决了并发的问题。
我们设计的不是同步FIFO吗?为什么要用异步ram呢?是不是成了异步FIFO?
当然不是,当然是同步FIFO,因为我们的syn_fifo模块中只有一个clk,其实子模块可以理所当然的用同步ram,但是,我们
这里之所以用异步ram,是因为当数据传入asyn_dp_ram模块时可以立刻被保存,不用再等上升沿的触发,如果用同步ram,
耗费了资源和功耗,还使数据保存延迟了一小段时间(从数据进入到等到clk上升沿到来这段时间)。
Code
1 `timescale 1ns/10ps
2
3 module syn_fifo(clk,
4 rst,
5 wr_cs,
6 wr_en,
7 din,
8 rd_cs,
9 rd_en,
10 dout,
11 empty,
12 full
13 );
14 parameter DATA_WIDTH=8;
15 parameter ADDR_WIDTH=8;
16 parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
17 input clk;
18 input rst;
19 input wr_cs;
20 input rd_cs;
21 input [DATA_WIDTH-1:0] din;
22 input rd_en;
23 input wr_en;
24 output [DATA_WIDTH-1:0] dout;
25 output empty;
26 output full;
27
28 reg [ADDR_WIDTH-1:0] wptr;
29 reg [ADDR_WIDTH-1:0] rptr;
30 reg [ADDR_WIDTH-1:0] status;
31 assign empty=(status==0);
32 assign full=(status==DEPT_WIDTH);
33 // write data into fifo
34 always@(posedge clk or posedge rst)
35 begin
36 if(rst)begin
37 wptr=0;
38 end
39 else if(wr_en&&wr_cs&&!full)begin
40 wptr=wptr+1;
41 end
42 end
43 //read data from fifo
44 always@(posedge clk or posedge rst)
45 begin
46 if(rst)begin
47 rptr=0;
48 end
49 else if(rd_en&&rd_cs&&!empty)begin
50 rptr=rptr+1;
51 end
52 end
53 //fifo status
54 always@(posedge clk or posedge rst)
55 begin
56 if(rst)begin
57 status=0;
58 end
59 else if((wr_en&&wr_cs)&&!(rd_en&&rd_cs)&&!full)begin
60 status=status+1;
61 end
62 else if(!(wr_en&&wr_cs)&&(rd_en&&rd_cs)&&!empty)begin
63 status=status-1;
64 end
65 else begin
66 status=status;
67 end
68 end
69 //double port asynchronized ram
70 asyn_dp_ram#(DATA_WIDTH,ADDR_WIDTH,DEPT_WIDTH)
71 u(.din(din),
72 .wptr(wptr),
73 .wr_en(wr_en),
74 .wr_cs(wr_cs),
75 .dout(dout),
76 .rptr(rptr),
77 .rd_en(rd_en),
78 .rd_cs(rd_cs)
79 );
80 endmodule
81
82
83
84 module asyn_dp_ram(din,wptr,wr_en,wr_cs,dout,rptr,rd_en,rd_cs);
85 parameter DATA_WIDTH=8;
86 parameter ADDR_WIDTH=8;
87 parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
88 input [DATA_WIDTH-1:0] din;
89 input [ADDR_WIDTH-1:0] wptr;
90 input [ADDR_WIDTH-1:0] rptr;
91 input wr_en;
92 input wr_cs;
93 input rd_en;
94 input rd_cs;
95 output [DATA_WIDTH-1:0] dout;
96
97 reg [DATA_WIDTH-1:0] dout;
98 reg [DATA_WIDTH-1:0] mem [DEPT_WIDTH-1:0];
99 //write data port
100 always@(din or wptr or wr_en or wr_cs)
101 begin
102 if(wr_en&&wr_cs)
103 mem[wptr]=din;
104 end
105 //read data port
106 always@(rptr or rd_en or rd_cs)
107 begin
108 if(rd_en&&rd_cs)
109 dout=mem[rptr];
110 end
111
112 endmodule
113
114
115
116
117
118 `timescale 1ns/10ps
119 module syn_fifo_testbench;
120 reg clk;
121 reg rst;
122 reg wr_cs;
123 reg rd_cs;
124 reg [7:0] din;
125 reg rd_en;
126 reg wr_en;
127 wire [7:0] dout;
128 wire empty;
129 wire full;
130 syn_fifo #(8,4)
131 u1(.clk(clk),
132 .rst(rst),
133 .wr_cs(wr_cs),
134 .wr_en(wr_en),
135 .din(din),
136 .rd_cs(rd_cs),
137 .rd_en(rd_en),
138 .dout(dout),
139 .empty(empty),
140 .full(full)
141 );
142 parameter p=10;
143 initial
144 begin
145 wr_cs=0;
146 wr_en=0;
147 rd_cs=0;
148 rd_en=0;
149 clk=0;
150 rst=1;
151 #p rst=0;
152 #p wr_cs=1;
153 wr_en=1;
154 din=8'b10101010;
155 #p din=8'b11001100;
156 #p din=8'b11111111;
157 #p wr_cs=0;
158 #p wr_en=0;
159 #p rd_cs=1;
160 #p rd_en=1;
161 #p ;
162 #p ;
163 #p rd_cs=0;
164 #p rd_en=0;
165 #1000 $finish;
166 end
167 initial
168 begin
169 $monitor("the din is %b ,out is %b at %d",din,dout,$time);
170 //$monitor("the dout is %b at %d",dout,$time);
171 end
172 always #5 clk=~clk;
173 endmodule
174
1 `timescale 1ns/10ps
2
3 module syn_fifo(clk,
4 rst,
5 wr_cs,
6 wr_en,
7 din,
8 rd_cs,
9 rd_en,
10 dout,
11 empty,
12 full
13 );
14 parameter DATA_WIDTH=8;
15 parameter ADDR_WIDTH=8;
16 parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
17 input clk;
18 input rst;
19 input wr_cs;
20 input rd_cs;
21 input [DATA_WIDTH-1:0] din;
22 input rd_en;
23 input wr_en;
24 output [DATA_WIDTH-1:0] dout;
25 output empty;
26 output full;
27
28 reg [ADDR_WIDTH-1:0] wptr;
29 reg [ADDR_WIDTH-1:0] rptr;
30 reg [ADDR_WIDTH-1:0] status;
31 assign empty=(status==0);
32 assign full=(status==DEPT_WIDTH);
33 // write data into fifo
34 always@(posedge clk or posedge rst)
35 begin
36 if(rst)begin
37 wptr=0;
38 end
39 else if(wr_en&&wr_cs&&!full)begin
40 wptr=wptr+1;
41 end
42 end
43 //read data from fifo
44 always@(posedge clk or posedge rst)
45 begin
46 if(rst)begin
47 rptr=0;
48 end
49 else if(rd_en&&rd_cs&&!empty)begin
50 rptr=rptr+1;
51 end
52 end
53 //fifo status
54 always@(posedge clk or posedge rst)
55 begin
56 if(rst)begin
57 status=0;
58 end
59 else if((wr_en&&wr_cs)&&!(rd_en&&rd_cs)&&!full)begin
60 status=status+1;
61 end
62 else if(!(wr_en&&wr_cs)&&(rd_en&&rd_cs)&&!empty)begin
63 status=status-1;
64 end
65 else begin
66 status=status;
67 end
68 end
69 //double port asynchronized ram
70 asyn_dp_ram#(DATA_WIDTH,ADDR_WIDTH,DEPT_WIDTH)
71 u(.din(din),
72 .wptr(wptr),
73 .wr_en(wr_en),
74 .wr_cs(wr_cs),
75 .dout(dout),
76 .rptr(rptr),
77 .rd_en(rd_en),
78 .rd_cs(rd_cs)
79 );
80 endmodule
81
82
83
84 module asyn_dp_ram(din,wptr,wr_en,wr_cs,dout,rptr,rd_en,rd_cs);
85 parameter DATA_WIDTH=8;
86 parameter ADDR_WIDTH=8;
87 parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
88 input [DATA_WIDTH-1:0] din;
89 input [ADDR_WIDTH-1:0] wptr;
90 input [ADDR_WIDTH-1:0] rptr;
91 input wr_en;
92 input wr_cs;
93 input rd_en;
94 input rd_cs;
95 output [DATA_WIDTH-1:0] dout;
96
97 reg [DATA_WIDTH-1:0] dout;
98 reg [DATA_WIDTH-1:0] mem [DEPT_WIDTH-1:0];
99 //write data port
100 always@(din or wptr or wr_en or wr_cs)
101 begin
102 if(wr_en&&wr_cs)
103 mem[wptr]=din;
104 end
105 //read data port
106 always@(rptr or rd_en or rd_cs)
107 begin
108 if(rd_en&&rd_cs)
109 dout=mem[rptr];
110 end
111
112 endmodule
113
114
115
116
117
118 `timescale 1ns/10ps
119 module syn_fifo_testbench;
120 reg clk;
121 reg rst;
122 reg wr_cs;
123 reg rd_cs;
124 reg [7:0] din;
125 reg rd_en;
126 reg wr_en;
127 wire [7:0] dout;
128 wire empty;
129 wire full;
130 syn_fifo #(8,4)
131 u1(.clk(clk),
132 .rst(rst),
133 .wr_cs(wr_cs),
134 .wr_en(wr_en),
135 .din(din),
136 .rd_cs(rd_cs),
137 .rd_en(rd_en),
138 .dout(dout),
139 .empty(empty),
140 .full(full)
141 );
142 parameter p=10;
143 initial
144 begin
145 wr_cs=0;
146 wr_en=0;
147 rd_cs=0;
148 rd_en=0;
149 clk=0;
150 rst=1;
151 #p rst=0;
152 #p wr_cs=1;
153 wr_en=1;
154 din=8'b10101010;
155 #p din=8'b11001100;
156 #p din=8'b11111111;
157 #p wr_cs=0;
158 #p wr_en=0;
159 #p rd_cs=1;
160 #p rd_en=1;
161 #p ;
162 #p ;
163 #p rd_cs=0;
164 #p rd_en=0;
165 #1000 $finish;
166 end
167 initial
168 begin
169 $monitor("the din is %b ,out is %b at %d",din,dout,$time);
170 //$monitor("the dout is %b at %d",dout,$time);
171 end
172 always #5 clk=~clk;
173 endmodule
174
完整代码