明德扬就业班现正火热招生中,课程主要传授至简设计法,100天的课程足以满足岗位需要,包就业推荐,详情点击咨询...

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

发布时间:2017-07-17

1、设计目的本项目展示如何用至简设计法设计SDARM,具体功能要求如下。

1)读写仲裁机制是:当如果同时出现读写请求时,如果上次执行了读操作,则此次执行写操作;如果上一次执行了写操作,则此次执行读操作。如果不是同时出现读写请求,则是什么请求就执行什么操作。

2)采用全页模式的读写操作,该模式在读、写完成时,需要给出预充电命令才能结束。

3)刷新请求始终优于读、写请求。

DDR的时序与SDRAM是相似的,学好SDRAM后,理解DDR2DDR3就非常容易了。

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群:544453837

更多FPGA技术资讯:明德扬科教

了解>>至简设计法


免费申请试听课程

  •   
  •   
  •   
  •  
  • 提  交
  • FPGA教育领域第一品牌
  • 咨询热线:020-39002701
  • 技术老师:1411324938
  • 技术Q群:97925396