打印
[FPGA]

至简设计法纯逻辑实现SDARM控制器

[复制链接]
493|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mdy郭柏荣|  楼主 | 2019-7-30 08:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1、设计目的本项目展示如何用至简设计法设计SDARM,具体功能要求如下。
1)读写仲裁机制是:当如果同时出现读写请求时,如果上次执行了读操作,则此次执行写操作;如果上一次执行了写操作,则此次执行读操作。如果不是同时出现读写请求,则是什么请求就执行什么操作。
2)采用全页模式的读写操作,该模式在读、写完成时,需要给出预充电命令才能结束。
3)刷新请求始终优于读、写请求。
DDR的时序与SDRAM是相似的,学好SDRAM后,理解DDR2和DDR3就非常容易了。
2、至简设计代码实现(附录部分代码)
下面是使用至简设计法实现的SDRAM控制器,该控制器使用了四段式状态机,其他信号根据状态机对齐而设计,结构相当清晰,无论是设计还是调试,都非常容易,相信有一定基础的工程师,能感觉到这样设计的精简、奇妙之处,欢迎借鉴、学习。
网络上亦有相当多的SDRAM实现代码,欢迎您拿来与明德扬对比,我们对自身的代码设计就是有这样的自信。
1 //四段式状态机
2
3 //第一段:同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
4 always@(posedge clk or negedge rst_n)begin
5 if(!rst_n)begin
6 state_c <= IDL;
7 end
8 else begin
9 state_c <= state_n;
10 end
11 end
12
13 //第二段:组合逻辑always模块,描述状态转移条件判断
14 //只需要思考转移到哪里去
15 always@(*)begin
16 case(state_c)
17 NOP:begin
18 if(nop2pre_start)begin
19 state_n = PRE;
20 end
21 else begin
22 state_n = state_c;
23 end
24 end
25 PRE:begin
26 if(pre2aut_start)begin
27 state_n = AUT;
28 end
29 else if(pre2idl_start)begin
30 state_n = IDL;
31 end
32
33 else begin
34 state_n = state_c;
35 end
36 end
37 AUT:begin
38 if(aut2aut_start)begin
39 state_n = AUT;
40 end
41 else if(aut2lmd_start)begin
42 state_n = LMD;
43 end
44 else if(aut2idl_start)begin
45 state_n = IDL;
46 end
47 end
48 LMD:begin
49 if(lmd2idl_start)begin
50 state_n = IDL;
51 end
52 else begin
53 state_n = state_c;
54 end
55 end
56 IDL:begin
57 if(idl2act_start)begin
58 state_n = ACT;
59 end
60 else if(idl2aut_start)begin
61 state_n = AUT;
62 end
63
64 else begin
65 state_n = state_c;
66 end
67 end
68 ACT:begin
69 if(act2red_start)begin
70 state_n = RED;
71 end
72 else if(act2wrt_start)begin
73 state_n = WRT;
74 end
75
76 else begin
77 state_n = state_c;
78 end
79 end
80 RED:begin
81 if(red2pre_start)begin
82 state_n = PRE;
83 end
84 else begin
85 state_n = state_c;
86 end
87 end
88 WRT:begin
89 if(wrt2pre_start)begin
90 state_n = PRE;
91 end
92 else begin
93 state_n = state_c;
94 end
95 end
96 default:begin
97 state_n = IDL;
98 end
99 endcase
100 end
101 //第三段:设计转移条件
102 //相同现态的要放在一起,条件互斥,方便比较
103 assign nop2pre_start = state_c==NOP && end_cnt;
104
105 assign pre2aut_start = state_c==PRE && init_flag==1 && end_cnt;
106 assign pre2idl_start = state_c==PRE && init_flag==0 && end_cnt;
107
108 assign aut2aut_start = state_c==AUT && init_flag==1 && init_auto_flag==1 && end_cnt;
109 assign aut2lmd_start = state_c==AUT && init_flag==1 && init_auto_flag==0 && end_cnt;
110
111 assign aut2idl_start = state_c==AUT && init_flag==0 && end_cnt;
112
113 assign lmd2idl_start = state_c==LMD && end_cnt;
114
115 assign idl2act_start = state_c==IDL && ref_req==0&& (wr_req||rd_req);
116 assign idl2aut_start = state_c==IDL && ref_req ==1 ;
117
118 assign act2red_start = state_c==ACT && rd_flag==1 && end_cnt;
119 assign act2wrt_start = state_c==ACT && rd_flag==0 && end_cnt;
120
121 assign red2pre_start = state_c==RED && end_cnt;
122 assign wrt2pre_start = state_c==WRT && end_cnt;
123
124 always @(posedge clk or negedge rst_n)begin
125 if(rst_n==1'b0)begin
126 init_flag <= 1;
127 end
128 else if(lmd2idl_start)begin
129 init_flag <= 0;
130 end
131 end
132
133 always @(posedge clk or negedge rst_n)begin
134 if(rst_n==1'b0)begin
135 init_auto_flag <= 1;
136 end
137 else if(aut2aut_start)begin
138 init_auto_flag <= 0;
139 end
140 end
141
142 //刷新请求
143 always @(posedge clk or negedge rst_n)begin
144 if(rst_n==1'b0)begin
145 ref_req <= 0;
146 end
147 else if(end_cnt_self)begin
148 ref_req <= 1;
149 end
150 else if(idl2aut_start)begin
151 ref_req <= 0;
152 end
153 end
154
155 //写响应
156 assign wr_ack = idl2act_start==1&& (wr_req==1&&((rd_flag==1)||(rd_flag==0&&rd_req==0)));
157 //读响应
158 assign rd_ack = idl2act_start==1&& (rd_req==1&&((rd_flag==0)||(rd_flag==1&&wr_req==0)));
159
160 always @(posedge clk or negedge rst_n)begin
161 if(rst_n==1'b0)begin
162 rd_flag <= 0;
163 end
164 else if(rd_flag==0&&rd_ack==1)begin
165 rd_flag <= 1;
166 end
167 else if(rd_flag==1&&wr_ack==1)begin
168 rd_flag <= 0;
169 end
170 end
171
172
173 //刷新时间计算
174 always @(posedge clk or negedge rst_n)begin
175 if(!rst_n)begin
176 cnt_self <= 0;
177 end
178 else if(add_cnt_self)begin
179 if(end_cnt_self)
180 cnt_self <= 0;
181 else
182 cnt_self <= cnt_self + 1;
183 end
184 end
185
186 assign add_cnt_self = init_flag==0;
187 assign end_cnt_self = add_cnt_self && cnt_self==1562-1 ;
188
189 //命令时间计数,此处使用了变量法,并且复用了一个计数器
190 always @(posedge clk or negedge rst_n)begin
191 if(!rst_n)begin
192 cnt <= 0;
193 end
194 else if(add_cnt)begin
195 if(end_cnt)
196 cnt <= 0;
197 else
198 cnt <= cnt + 1;
199 end
200 end
201
202 assign add_cnt = state_c!=IDL;
203 assign end_cnt = add_cnt && cnt==x-1 ;
204
205 //各个命令所需要的时间,在下面列出来就好了
206 always @(*)begin
207 if(state_c==NOP)begin
208 x = INITIATE;
209 end
210 else if(state_c==PRE)begin
211 x = TRP;
212 end
213 else if(state_c==AUT)begin
214 x = TRC;
215 end
216 else if(state_c==LMD)begin
217 x = TMRD;
218 end
219 else if(state_c==ACT)begin
220 x = TRCD ;
221 end
222 else begin
223 x = 256 ;
224 end
225 end
226
227 always @(posedge clk or negedge rst_n)begin
228 if(rst_n==1'b0)begin
229 cke <= 1;
230 end
231 else begin
232 cke <= 1;
233 end
234 end
235
236 assign command = {cs,ras,cas,we};
237
238 //下面是产生命令的代码,由于状态机结构简单,要产生COMMAND是非常方便的
239 //仅从名字下就可以看出代码是否正确
240 always @(posedge clk or negedge rst_n)begin
241 if(rst_n==1'b0)begin
242 command <= 0;
243 end
244 else if(nop2pre_start||wrt2pre_start||red2pre_start)begin
245 command <= precharge;
246 end
247 else if(pre2aut_start||aut2aut_start||idl2aut_start)begin
248 command <= autorefresh;
249 end
250 else if(aut2lmd_start)begin
251 command <= loadmode;
252 end
253 else if(idl2act_start)begin
254 command <= active;
255 end
256 else if(act2red_start)begin
257 command <= read;
258 end
259 else if(act2wrt_start)begin
260 command <= write;
261 end
262 else begin
263 command <= nop;
264 end
265
266 end
267
268 always @(posedge clk or negedge rst_n)begin
269 if(rst_n==1'b0)begin
270 dqm <= 0;
271 end
272 else if(init_flag==1)begin
273 dqm <= 2'b11;
274 end
275 else begin
276 dqm <= 0;
277 end
278 end
279
280 always @(posedge clk or negedge rst_n)begin
281 if(rst_n==1'b0)begin
282 dq_out <= 0;
283 end
284 else begin
285 dq_out <= wdata;
286 end
287 end
288
289 always @(posedge clk or negedge rst_n)begin
290 if(rst_n==1'b0)begin
291 dq_out_en <= 0;
292 end
293 else if(act2wrt_start)begin
294 dq_out_en <= 1;
295 end
296 else if(wrt2pre_start)begin
297 dq_out_en <= 0;
298 end
299 end
300
301
302 always @(posedge clk or negedge rst_n)begin //256拍
303 if(rst_n==1'b0)begin
304 rdata_flag <= 0;
305 end
306 else if(act2red_start)begin
307 rdata_flag <= 1;
308 end
309 else if(red2pre_start)begin
310 rdata_flag <= 0;
311 end
312 end
313
314 always @(posedge clk or negedge rst_n)begin
315 if(rst_n==1'b0)begin
316 rdata_flag_ff0 <= 0;
317 rdata_flag_ff1 <= 0;
318 rdata_flag_ff2 <= 0;
319 end
320 else begin
321 rdata_flag_ff0 <= rdata_flag;
322 rdata_flag_ff1 <= rdata_flag_ff0;
323 rdata_flag_ff2 <= rdata_flag_ff1;
324
325 end
326 end
327
328
329 always @(posedge clk or negedge rst_n)begin
330 if(rst_n==1'b0)begin
331 rdata <= 0;
332 end
333 else begin
334 rdata <= dq_in;
335 end
336
337 end
338
339 always @(posedge clk or negedge rst_n)begin
340 if(rst_n==1'b0)begin
341 rdata_vld <= 0;
342 end
343 else begin
344 rdata_vld <= rd_flag_ff2;
345 end
346 end
347
348 always @(posedge clk or negedge rst_n)begin //锁存地址waddr;
349 if(rst_n==1'b0)begin
350 waddr_ff0 <= 0;
351 end
352 else if(idl2act_start)begin
353 waddr_ff0 <= waddr;
354 end
355 end
356
357 always @(posedge clk or negedge rst_n)begin
358 if(rst_n==1'b0)begin
359 addr <= 0;
360 end
361 else if(nop2pre_start)begin
362 addr <=12'b0100_0000_0000;
363 end
364 else if(aut2lmd_start)begin
365 addr <= 12'b00_1_00_010_0_111;//latency Mode 为010 的情况
366 end
367 else if(idl2act_start)begin
368 addr[7:0] <= waddr[19:8]; //行地址
369 end
370 else if(act2wrt_start||act2red_start)begin
371 addr[7:0] <= waddr_ff0[7:0]; //列地址
372 end
373 end
374
375 always @(posedge clk or negedge rst_n)begin
376 if(rst_n==1'b0)begin
377 bank <=0;
378 end
379 else if(nop2pre_start)begin
380 bank <= 2'b11;
381 end
382 else if(idl2act_start)begin
383 bank <= waddr[21:20];
384 end
385 else if(act2red_start||act2wrt_start)begin
386 bank < waddr_ff0[21:20];
387 end
388 else begin
389 bank <= 0;
390 end
391 end
392
393
394
395

QQ   1465617980
了解>>至简设计法


使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

34

主题

116

帖子

1

粉丝