/* SDRAM Controller 2007/2/14 IS42S16400 1M Words x 16 bits x 4 Banks (64Mbit) clock 50 MHz bank<2> adrs<20> data<16> QuartusII 7.2 177LC 125DLR */ circuit sdram_ctrl { output CSn, RASn, CASn, WEn; output LDM, HDM; output DEn; // Write data output enable output BA<2>, A<12>; input Din<16>; output Dout<16>; instrin write(adrs, wdata); input wdata<16>, adrs<22>; instrin read(adrs); output rdata<16>, ack; output err; reg_wr err_reg; reg_wr BA_reg<2>; reg_ws A_reg<12>; // reg_ws LDM_reg, HDM_reg; reg_ws RASn_reg, CASn_reg, WEn_reg, DEn_reg; reg_ws reset; reg_wr init_count<16>; // use <14> reg_wr adrs_reg<22>, rdata_reg<16>, wdata_reg<16>; instrself com_NOP, com_PRE, com_REF, com_MRS, com_ACT, com_WRITE, com_READ; stage_name init { task do(); } stage_name refresh { task do(); } stage_name refresh_cnt { task do(); } stage_name swrite { task do(adrs_reg, wdata_reg); } stage_name sread { task do(adrs_reg); } par{ if(reset){ reset := 0b0; generate init.do(); } ack = ^(init.do | sread.do | swrite.do); CSn = 0b0; LDM = 0b0; // LDM_reg; HDM = 0b0; // HDM_reg; RASn = RASn_reg; CASn = CASn_reg; WEn = WEn_reg; DEn = DEn_reg; BA = BA_reg; A = A_reg; Dout = wdata_reg; rdata = rdata_reg; init_count++; } instruct read par{ generate sread.do(adrs); } instruct write par{ generate swrite.do(adrs, wdata); } instruct com_NOP par{ RASn_reg := 0b1; CASn_reg := 0b1; WEn_reg := 0b1; } // Trp 20 ns instruct com_PRE par{ RASn_reg := 0b0; CASn_reg := 0b1; WEn_reg := 0b0; } // Trc 70 ns instruct com_REF par{ RASn_reg := 0b0; CASn_reg := 0b0; WEn_reg := 0b1; } // Trc 10 ns instruct com_MRS par{ RASn_reg := 0b0; CASn_reg := 0b0; WEn_reg := 0b0; } // Trcd 20 ns instruct com_ACT par{ RASn_reg := 0b0; CASn_reg := 0b1; WEn_reg := 0b1; } instruct com_WRITE par{ RASn_reg := 0b1; CASn_reg := 0b0; WEn_reg := 0b0; } instruct com_READ par{ RASn_reg := 0b1; CASn_reg := 0b0; WEn_reg := 0b1; } stage init { state_name st_PON,st_PALL,st_wPALL1,st_wPALL2,st_REF,st_wREF,st_MRS,st_wMRS; first_state st_PON; state st_PON par{ com_NOP(); if(init_count<14>) goto st_PALL; } state st_PALL par{ com_PRE(); A_reg := 0b010000000000; // All banks goto st_wPALL1; } state st_wPALL1 par{ com_NOP(); goto st_wPALL2; } state st_wPALL2 par{ com_NOP(); if(/&init_count<5:0>) goto st_REF; } state st_REF par{ if(init_count<2:0>==0b000) com_REF(); else com_NOP(); if(/&init_count<5:0>) goto st_wREF; } state st_wREF par{ goto st_MRS; } state st_MRS par{ com_MRS(); BA_reg := 0b00; A_reg := 0b00000 || 0b010 || 0b0000; // CAS 2 Burst 1 goto st_wMRS; } state st_wMRS par{ com_NOP(); // 4回以上 if(init_count<3>) relay refresh_cnt.do(); } } stage swrite { state_name st_ACT, st_WRITEA, st_w1; first_state st_ACT; state st_ACT if(^refresh.do){ com_ACT(); BA_reg := adrs_reg<21:20>; A_reg := adrs_reg<19:8>; DEn_reg := 0b0; goto st_WRITEA; } state st_WRITEA par{ com_WRITE(); A_reg := 0b0100 || adrs_reg<7:0>; goto st_w1; } state st_w1 par{ com_NOP(); DEn_reg := 0b1; goto st_ACT; finish; } } stage sread { reg_wr ap; state_name st_ACT,st_READA,st_w0,st_w1,st_w2; first_state st_ACT; state st_ACT if(^refresh.do){ com_ACT(); BA_reg := adrs_reg<21:20>; A_reg := adrs_reg<19:8>; goto st_READA; } state st_READA par{ com_READ(); A_reg := 0b0100 || adrs_reg<7:0>; goto st_w0; } state st_w0 par{ com_NOP(); ap := ^ap; if(ap) goto st_w2; // オートプリチャージ } state st_w2 par{ // CL 2 rdata_reg := Din; goto st_ACT; finish; } } stage refresh_cnt { reg_wr refresh_time<7>; reg_wr notused; state_name st1,st2; first_state st1; if(notused) finish; state st1 if(^refresh.do){ refresh_time++; if(/&refresh_time) goto st2; } state st2 if(^(sread.do | swrite.do)){ generate refresh.do(); goto st1; } } // read と refresh が同時に起動しても refresh を優先 stage refresh { reg_wr refresh_A<14>; state_name st_ACT, st_PRE, st_wPRE; first_state st_ACT; state st_ACT par{ com_ACT(); BA_reg := refresh_A<1:0>; A_reg := refresh_A<13:2>; goto st_PRE; } state st_PRE par{ com_PRE(); A_reg := 0b010000000000; refresh_A++; goto st_wPRE; } state st_wPRE par{ com_NOP(); goto st_ACT; finish; } } }