SDRAM驱动设计(未完待续)
一、SDRAM初始化模块代码
1 // ********************************************************************************* 2 // Project Name : sdram_driver 3 // Email : 4 // Create Time : 2020/11/11 15:05 5 // Module Name : sdram_init 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module sdram_init( 11 input sclk , 12 input s_rst_n , 13 14 output reg[3:0] init_cmd , // 初始化命令 15 output reg[1:0] init_bank , // 初始化Bank地址 16 output reg[12:0] init_addr , // 17 18 output wire init_end // 初始化结束信号 19 ); 20 21 //========================================================================\ 22 // =========== Define Parameter and Internal signals =========== 23 //========================================================================/ 24 25 // --------------------- 状态位 --------------------------- 26 27 parameter INIT_NOP = 4'b0000 ; // 初始化状态 28 parameter INIT_PRE = 4'b0001 ; // 预充电状态 29 parameter INIT_REF1 = 4'b0010 ; // 自动刷新状态1 30 parameter INIT_REF2 = 4'b0011 ; // 自动刷新状态2 31 parameter INIT_MODE = 4'b0100 ; // 加载模式寄存器状态 32 parameter INIT_END = 4'b0101 ; // 初始化结束状态 33 34 // --------------------- 命令位 ---------------------------- 35 36 parameter CMD_NOP = 4'b0111 ; // 空操作指令 37 parameter CMD_PRE = 4'b0010 ; // 预充电指令 38 parameter CMD_REF = 4'b0001 ; // 自动刷新指令 39 parameter CMD_MODE = 4'b0000 ; // 加载模式寄存器指令 40 41 // --------------------- 时间参数设置 ---------------------------- 42 43 parameter TIME_200US = 20000 ; 44 parameter TIME_TRP = 2 ; 45 parameter TIME_TRC = 7 ; 46 parameter TIME_TMRD = 2 ; 47 48 // ---------------------- 寄存器设置 ----------------------------- 49 50 reg [15:0] cnt0 ; 51 reg [15:0] x ; 52 wire add_cnt0 ; 53 wire end_cnt0 ; 54 55 reg [3:0] current_state ; 56 reg [3:0] next_state ; 57 58 wire start_init_pre ; 59 wire start_init_ref1 ; 60 wire start_init_ref2 ; 61 wire start_init_mode ; 62 wire start_init_end ; 63 64 //============================================================================= 65 //**************************** Main Code ******************************* 66 //============================================================================= 67 68 always @ (posedge sclk or negedge s_rst_n) begin 69 if(s_rst_n == 1'b0) 70 current_state <= INIT_NOP; 71 else 72 current_state <= next_state; 73 end 74 75 always @ (*) begin 76 case(current_state) 77 INIT_NOP:begin 78 if(start_init_pre == 1'b1) 79 next_state = INIT_PRE; 80 else 81 next_state = current_state; 82 end 83 INIT_PRE:begin 84 if(start_init_ref1 == 1'b1) 85 next_state = INIT_REF1; 86 else 87 next_state = current_state; 88 end 89 INIT_REF1:begin 90 if(start_init_ref2 == 1'b1) 91 next_state = INIT_REF2; 92 else 93 next_state = current_state; 94 end 95 INIT_REF2:begin 96 if(start_init_mode == 1'b1) 97 next_state = INIT_MODE; 98 else 99 next_state = current_state; 100 end 101 INIT_MODE:begin 102 if(start_init_end == 1'b1) 103 next_state = INIT_END; 104 else 105 next_state = current_state; 106 end 107 INIT_END:begin 108 next_state = INIT_END; 109 end 110 default:begin 111 next_state = INIT_NOP; 112 end 113 endcase 114 end 115 116 assign start_init_pre = (current_state == INIT_NOP) && end_cnt0 ; 117 assign start_init_ref1 = (current_state == INIT_PRE) && end_cnt0 ; 118 assign start_init_ref2 = (current_state == INIT_REF1) && end_cnt0 ; 119 assign start_init_mode = (current_state == INIT_REF2) && end_cnt0 ; 120 assign start_init_end = (current_state == INIT_MODE) && end_cnt0 ; 121 122 123 always @(posedge sclk or negedge s_rst_n) begin 124 if(!s_rst_n) 125 cnt0 <= 0; 126 else if(add_cnt0) begin 127 if(end_cnt0) 128 cnt0 <= 0; 129 else 130 cnt0 <= cnt0 + 1'b1; 131 end 132 end 133 134 assign add_cnt0 = current_state != INIT_END; 135 assign end_cnt0 = add_cnt0 && cnt0 == x - 1; 136 137 always @(*) begin 138 if(!s_rst_n) 139 x = TIME_200US; 140 else if(current_state == INIT_PRE) 141 x = TIME_TRP; 142 else if(current_state == INIT_REF1 || current_state == INIT_REF2) 143 x = TIME_TRC; 144 else if(current_state == INIT_MODE) 145 x = TIME_TMRD; 146 else 147 x = TIME_200US; 148 end 149 150 always @(posedge sclk or negedge s_rst_n) begin 151 if(!s_rst_n) 152 init_cmd <= CMD_NOP; 153 else if(start_init_pre == 1'b1) 154 init_cmd <= CMD_PRE; 155 else if(start_init_ref1 == 1'b1 || start_init_ref2 == 1'b1) 156 init_cmd <= CMD_REF; 157 else if(start_init_mode == 1'b1) 158 init_cmd <= CMD_MODE; 159 else 160 init_cmd <= CMD_NOP; 161 end 162 163 always @(posedge sclk or negedge s_rst_n) begin 164 if(!s_rst_n) 165 init_bank <= 2'b00; 166 else 167 init_bank <= 2'b11; 168 end 169 170 always @(posedge sclk or negedge s_rst_n) begin 171 if(!s_rst_n) 172 init_addr <= 13'b0; 173 else if(start_init_pre == 1'b1) 174 init_addr <= 13'b0010_0000_00000; 175 else if(start_init_mode == 1'b1) 176 init_addr <= 13'b00000_0010_0111; 177 else 178 init_addr <= 13'b0; 179 end 180 181 assign init_end = (start_init_end == 1'b1); 182 183 endmodule
Testbench:
1 `timescale 1ns/1ns 2 module sdram_init_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 wire [3:0] init_cmd ; // 初始化命令 6 wire [1:0] init_bank ; // 初始化Bank地址 7 wire [12:0] init_addr ; // 8 wire init_end ; // 初始化结束信号 9 10 sdram_init sdram_init_inst( 11 .sclk ( sclk ), 12 .s_rst_n ( s_rst_n ), 13 .init_cmd ( init_cmd ), 14 .init_bank ( init_bank ), 15 .init_addr ( init_addr ), 16 .init_end ( init_end ) 17 ); 18 19 sdram_model_plus sdram_model_plus_inst( 20 .Dq ( ), 21 .Addr (init_addr ), 22 .Ba (init_bank ), 23 .Clk (~sclk ), // 24 .Cke (1'b1 ), 25 .Cs_n (init_cmd[3] ), 26 .Ras_n (init_cmd[2] ), 27 .Cas_n (init_cmd[1] ), 28 .We_n (init_cmd[0] ), 29 .Dqm (2'b0 ), 30 .Debug (1'b1 ) 31 ); 32 33 defparam sdram_model_plus_inst.addr_bits = 13; 34 defparam sdram_model_plus_inst.data_bits = 16; 35 defparam sdram_model_plus_inst.col_bits = 9; 36 defparam sdram_model_plus_inst.mem_sizes = 2*1024*1024; 37 38 initial 39 sclk = 1'b0; 40 always #5 sclk = ~sclk; 41 42 initial 43 begin 44 s_rst_n = 1'b0; 45 #21; 46 s_rst_n = 1'b1; 47 end 48 49 endmodule
1 /*************************************************************************************** 2 作者: 李晟 3 2003-08-27 V0.1 李晟 4 5 添加内存模块倒空功能,在外部需要创建事件:sdram_r ,本SDRAM的内容将会按Bank 顺序damp out 至文件 6 sdram_data.txt 中 7 ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/ 8 //2004-03-04 陈乃奎 修改原程序中将BANK的数据转存入TXT文件的格式 9 //2004-03-16 陈乃奎 修改SDRAM 的初始化数据 10 //2004/04/06 陈乃奎 将SDRAM的操作命令以字符形式表示,以便用MODELSIM监视 11 //2004/04/19 陈乃奎 修改参数 parameter tAC = 8; 12 //2010/09/17 罗瑶 修改sdram的大小,数据位宽,dqm宽度; 13 /**************************************************************************************** 14 * 15 * File Name: sdram_model.V 16 * Version: 0.0f 17 * Date: July 8th, 1999 18 * Model: BUS Functional 19 * Simulator: Model Technology (PC version 5.2e PE) 20 * 21 * Dependencies: None 22 * 23 * Author: Son P. Huynh 24 * Email: sphuynh@micron.com 25 * Phone: (208) 368-3825 26 * Company: Micron Technology, Inc. 27 * Model: sdram_model (1Meg x 16 x 4 Banks) 28 * 29 * Description: 64Mb SDRAM Verilog model 30 * 31 * Limitation: - Doesn't check for 4096 cycle refresh 32 * 33 * Note: - Set simulator resolution to "ps" accuracy 34 * - Set Debug = 0 to disable $display messages 35 * 36 * Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY 37 * WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY 38 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR 39 * A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. 40 * 41 * Copyright ?1998 Micron Semiconductor Products, Inc. 42 * All rights researved 43 * 44 * Rev Author Phone Date Changes 45 * ---- ---------------------------- ---------- --------------------------------------- 46 * 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto) 47 * Micron Technology Inc. - Fix tWR = 15 ns (Manual) 48 * - Fix tRP (Autoprecharge to AutoRefresh) 49 * 50 * 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e) 51 * Micron Technology Inc. 52 ****************************************************************************************/ 53 54 `timescale 1ns / 100ps 55 56 module sdram_model_plus (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm,Debug); 57 58 parameter addr_bits = 11; 59 parameter data_bits = 32; 60 parameter col_bits = 8; 61 parameter mem_sizes = 1048576*2-1;//1 Meg 62 63 inout [data_bits - 1 : 0] Dq; 64 input [addr_bits - 1 : 0] Addr; 65 input [1 : 0] Ba; 66 input Clk; 67 input Cke; 68 input Cs_n; 69 input Ras_n; 70 input Cas_n; 71 input We_n; 72 input [3 : 0] Dqm; //高低各8bit 73 //added by xzli 74 input Debug; 75 76 reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];//存储器类型数据 77 reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes]; 78 reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes]; 79 reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes]; 80 81 reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline 82 reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline 83 reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline 84 reg [3 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline 85 reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; 86 87 reg [addr_bits - 1 : 0] Mode_reg; 88 reg [data_bits - 1 : 0] Dq_reg, Dq_dqm; 89 reg [col_bits - 1 : 0] Col_temp, Burst_counter; 90 91 reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate 92 reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge 93 94 reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command 95 reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks) 96 reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank) 97 reg Read_precharge [0 : 3]; // R AutoPrecharge 98 reg Write_precharge [0 : 3]; // W AutoPrecharge 99 integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter) 100 reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge 101 reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge 102 103 reg Data_in_enable; 104 reg Data_out_enable; 105 106 reg [1 : 0] Bank, Previous_bank; 107 reg [addr_bits - 1 : 0] Row; 108 reg [col_bits - 1 : 0] Col, Col_brst; 109 110 // Internal system clock 111 reg CkeZ, Sys_clk; 112 113 reg [21:0] dd; 114 115 // Commands Decode 116 wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; 117 wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; 118 wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; 119 wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n; 120 wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; 121 wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; 122 wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; 123 124 // Burst Length Decode 125 wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0]; 126 wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0]; 127 wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0]; 128 wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0]; 129 130 // CAS Latency Decode 131 wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4]; 132 wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4]; 133 134 // Write Burst Mode 135 wire Write_burst_mode = Mode_reg[9]; 136 137 wire Debug; // Debug messages : 1 = On; 0 = Off 138 wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ 139 140 reg [31:0] mem_d; 141 142 event sdram_r,sdram_w,compare; 143 144 145 146 147 assign Dq = Dq_reg; // DQ buffer 148 149 // Commands Operation 150 `define ACT 0 151 `define NOP 1 152 `define READ 2 153 `define READ_A 3 154 `define WRITE 4 155 `define WRITE_A 5 156 `define PRECH 6 157 `define A_REF 7 158 `define BST 8 159 `define LMR 9 160 161 // // Timing Parameters for -75 (PC133) and CAS Latency = 2 162 // parameter tAC = 8; //test 6.5 163 // parameter tHZ = 7.0; 164 // parameter tOH = 2.7; 165 // parameter tMRD = 2.0; // 2 Clk Cycles 166 // parameter tRAS = 44.0; 167 // parameter tRC = 66.0; 168 // parameter tRCD = 20.0; 169 // parameter tRP = 20.0; 170 // parameter tRRD = 15.0; 171 // parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) 172 // parameter tWRp = 0.0; // A2 Version - Precharge mode only (15 ns) 173 174 // Timing Parameters for -7 (PC143) and CAS Latency = 3 175 parameter tAC = 6.5; //test 6.5 176 parameter tHZ = 5.5; 177 parameter tOH = 2; 178 parameter tMRD = 2.0; // 2 Clk Cycles 179 parameter tRAS = 48.0; 180 parameter tRC = 70.0; 181 parameter tRCD = 20.0; 182 parameter tRP = 20.0; 183 parameter tRRD = 14.0; 184 parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) 185 parameter tWRp = 0.0; // A2 Version - Precharge mode only (15 ns) 186 187 // Timing Check variable 188 integer MRD_chk; 189 integer WR_counter [0 : 3]; 190 time WR_chk [0 : 3]; 191 time RC_chk, RRD_chk; 192 time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; 193 time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; 194 time RP_chk0, RP_chk1, RP_chk2, RP_chk3; 195 196 integer test_file; 197 198 //*****display the command of the sdram************************************** 199 200 parameter Mode_Reg_Set =4'b0000; 201 parameter Auto_Refresh =4'b0001; 202 parameter Row_Active =4'b0011; 203 parameter Pre_Charge =4'b0010; 204 parameter PreCharge_All =4'b0010; 205 parameter Write =4'b0100; 206 parameter Write_Pre =4'b0100; 207 parameter Read =4'b0101; 208 parameter Read_Pre =4'b0101; 209 parameter Burst_Stop =4'b0110; 210 parameter Nop =4'b0111; 211 parameter Dsel =4'b1111; 212 213 wire [3:0] sdram_control; 214 reg cke_temp; 215 reg [8*13:1] sdram_command; 216 217 always@(posedge Clk) 218 cke_temp<=Cke; 219 220 assign sdram_control={Cs_n,Ras_n,Cas_n,We_n}; 221 222 always@(sdram_control or cke_temp) 223 begin 224 case(sdram_control) 225 Mode_Reg_Set: sdram_command<="Mode_Reg_Set"; 226 Auto_Refresh: sdram_command<="Auto_Refresh"; 227 Row_Active: sdram_command<="Row_Active"; 228 Pre_Charge: sdram_command<="Pre_Charge"; 229 Burst_Stop: sdram_command<="Burst_Stop"; 230 Dsel: sdram_command<="Dsel"; 231 232 Write: if(cke_temp==1) 233 sdram_command<="Write"; 234 else 235 sdram_command<="Write_suspend"; 236 237 Read: if(cke_temp==1) 238 sdram_command<="Read"; 239 else 240 sdram_command<="Read_suspend"; 241 242 Nop: if(cke_temp==1) 243 sdram_command<="Nop"; 244 else 245 sdram_command<="Self_refresh"; 246 247 default: sdram_command<="Power_down"; 248 endcase 249 end 250 251 //***************************************************** 252 253 initial 254 begin 255 //test_file=$fopen("test_file.txt"); 256 end 257 258 initial 259 begin 260 Dq_reg = {data_bits{1'bz}}; 261 {Data_in_enable, Data_out_enable} = 0; 262 {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; 263 {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000; 264 {WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0; 265 {WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0; 266 {RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0; 267 {RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0; 268 {MRD_chk, RC_chk, RRD_chk} = 0; 269 {RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0; 270 {RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0; 271 {RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0; 272 $timeformat (-9, 0, " ns", 12); 273 //$readmemh("bank0.txt", Bank0); 274 //$readmemh("bank1.txt", Bank1); 275 //$readmemh("bank2.txt", Bank2); 276 //$readmemh("bank3.txt", Bank3); 277 /* 278 for(dd=0;dd<=mem_sizes;dd=dd+1) 279 begin 280 Bank0[dd]=dd[data_bits - 1 : 0]; 281 Bank1[dd]=dd[data_bits - 1 : 0]+1; 282 Bank2[dd]=dd[data_bits - 1 : 0]+2; 283 Bank3[dd]=dd[data_bits - 1 : 0]+3; 284 end 285 */ 286 initial_sdram(0); 287 end 288 289 task initial_sdram; 290 291 input data_sign; 292 reg [3:0] data_sign; 293 294 for(dd=0;dd<=mem_sizes;dd=dd+1) 295 begin 296 mem_d = {data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign}; 297 if(data_bits==16) 298 begin 299 Bank0[dd]=mem_d[15:0]; 300 Bank1[dd]=mem_d[15:0]; 301 Bank2[dd]=mem_d[15:0]; 302 Bank3[dd]=mem_d[15:0]; 303 end 304 else if(data_bits==32) 305 begin 306 Bank0[dd]=mem_d[31:0]; 307 Bank1[dd]=mem_d[31:0]; 308 Bank2[dd]=mem_d[31:0]; 309 Bank3[dd]=mem_d[31:0]; 310 end 311 end 312 313 endtask 314 315 // System clock generator 316 always 317 begin 318 @(posedge Clk) 319 begin 320 Sys_clk = CkeZ; 321 CkeZ = Cke; 322 end 323 @(negedge Clk) 324 begin 325 Sys_clk = 1'b0; 326 end 327 end 328 329 always @ (posedge Sys_clk) begin 330 // Internal Commamd Pipelined 331 Command[0] = Command[1]; 332 Command[1] = Command[2]; 333 Command[2] = Command[3]; 334 Command[3] = `NOP; 335 336 Col_addr[0] = Col_addr[1]; 337 Col_addr[1] = Col_addr[2]; 338 Col_addr[2] = Col_addr[3]; 339 Col_addr[3] = {col_bits{1'b0}}; 340 341 Bank_addr[0] = Bank_addr[1]; 342 Bank_addr[1] = Bank_addr[2]; 343 Bank_addr[2] = Bank_addr[3]; 344 Bank_addr[3] = 2'b0; 345 346 Bank_precharge[0] = Bank_precharge[1]; 347 Bank_precharge[1] = Bank_precharge[2]; 348 Bank_precharge[2] = Bank_precharge[3]; 349 Bank_precharge[3] = 2'b0; 350 351 A10_precharge[0] = A10_precharge[1]; 352 A10_precharge[1] = A10_precharge[2]; 353 A10_precharge[2] = A10_precharge[3]; 354 A10_precharge[3] = 1'b0; 355 356 // Dqm pipeline for Read 357 Dqm_reg0 = Dqm_reg1; 358 Dqm_reg1 = Dqm; 359 360 // Read or Write with Auto Precharge Counter 361 if (Auto_precharge[0] == 1'b1) begin 362 Count_precharge[0] = Count_precharge[0] + 1; 363 end 364 if (Auto_precharge[1] == 1'b1) begin 365 Count_precharge[1] = Count_precharge[1] + 1; 366 end 367 if (Auto_precharge[2] == 1'b1) begin 368 Count_precharge[2] = Count_precharge[2] + 1; 369 end 370 if (Auto_precharge[3] == 1'b1) begin 371 Count_precharge[3] = Count_precharge[3] + 1; 372 end 373 374 // tMRD Counter 375 MRD_chk = MRD_chk + 1; 376 377 // tWR Counter for Write 378 WR_counter[0] = WR_counter[0] + 1; 379 WR_counter[1] = WR_counter[1] + 1; 380 WR_counter[2] = WR_counter[2] + 1; 381 WR_counter[3] = WR_counter[3] + 1; 382 383 // Auto Refresh 384 if (Aref_enable == 1'b1) begin 385 if (Debug) $display ("at time %t AREF : Auto Refresh", $time); 386 // Auto Refresh to Auto Refresh 387 if (($time - RC_chk < tRC)&&Debug) begin 388 $display ("at time %t ERROR: tRC violation during Auto Refresh", $time); 389 end 390 // Precharge to Auto Refresh 391 if (($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP)&&Debug) begin 392 $display ("at time %t ERROR: tRP violation during Auto Refresh", $time); 393 end 394 // Precharge to Refresh 395 if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin 396 $display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time); 397 end 398 // Record Current tRC time 399 RC_chk = $time; 400 end 401 402 // Load Mode Register 403 if (Mode_reg_enable == 1'b1) begin 404 // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode 405 if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin 406 Mode_reg = Addr; 407 if (Debug) begin 408 $display ("at time %t LMR : Load Mode Register", $time); 409 // CAS Latency 410 if (Addr[6 : 4] == 3'b010) 411 $display (" CAS Latency = 2"); 412 else if (Addr[6 : 4] == 3'b011) 413 $display (" CAS Latency = 3"); 414 else 415 $display (" CAS Latency = Reserved"); 416 // Burst Length 417 if (Addr[2 : 0] == 3'b000) 418 $display (" Burst Length = 1"); 419 else if (Addr[2 : 0] == 3'b001) 420 $display (" Burst Length = 2"); 421 else if (Addr[2 : 0] == 3'b010) 422 $display (" Burst Length = 4"); 423 else if (Addr[2 : 0] == 3'b011) 424 $display (" Burst Length = 8"); 425 else if (Addr[3 : 0] == 4'b0111) 426 $display (" Burst Length = Full"); 427 else 428 $display (" Burst Length = Reserved"); 429 // Burst Type 430 if (Addr[3] == 1'b0) 431 $display (" Burst Type = Sequential"); 432 else if (Addr[3] == 1'b1) 433 $display (" Burst Type = Interleaved"); 434 else 435 $display (" Burst Type = Reserved"); 436 // Write Burst Mode 437 if (Addr[9] == 1'b0) 438 $display (" Write Burst Mode = Programmed Burst Length"); 439 else if (Addr[9] == 1'b1) 440 $display (" Write Burst Mode = Single Location Access"); 441 else 442 $display (" Write Burst Mode = Reserved"); 443 end 444 end else begin 445 $display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); 446 end 447 // REF to LMR 448 if ($time - RC_chk < tRC) begin 449 $display ("at time %t ERROR: tRC violation during Load Mode Register", $time); 450 end 451 // LMR to LMR 452 if (MRD_chk < tMRD) begin 453 $display ("at time %t ERROR: tMRD violation during Load Mode Register", $time); 454 end 455 MRD_chk = 0; 456 end 457 458 // Active Block (Latch Bank Address and Row Address) 459 if (Active_enable == 1'b1) begin 460 if (Ba == 2'b00 && Pc_b0 == 1'b1) begin 461 {Act_b0, Pc_b0} = 2'b10; 462 B0_row_addr = Addr [addr_bits - 1 : 0]; 463 RCD_chk0 = $time; 464 RAS_chk0 = $time; 465 if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr); 466 // Precharge to Activate Bank 0 467 if ($time - RP_chk0 < tRP) begin 468 $display ("at time %t ERROR: tRP violation during Activate bank 0", $time); 469 end 470 end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin 471 {Act_b1, Pc_b1} = 2'b10; 472 B1_row_addr = Addr [addr_bits - 1 : 0]; 473 RCD_chk1 = $time; 474 RAS_chk1 = $time; 475 if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr); 476 // Precharge to Activate Bank 1 477 if ($time - RP_chk1 < tRP) begin 478 $display ("at time %t ERROR: tRP violation during Activate bank 1", $time); 479 end 480 end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin 481 {Act_b2, Pc_b2} = 2'b10; 482 B2_row_addr = Addr [addr_bits - 1 : 0]; 483 RCD_chk2 = $time; 484 RAS_chk2 = $time; 485 if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr); 486 // Precharge to Activate Bank 2 487 if ($time - RP_chk2 < tRP) begin 488 $display ("at time %t ERROR: tRP violation during Activate bank 2", $time); 489 end 490 end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin 491 {Act_b3, Pc_b3} = 2'b10; 492 B3_row_addr = Addr [addr_bits - 1 : 0]; 493 RCD_chk3 = $time; 494 RAS_chk3 = $time; 495 if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr); 496 // Precharge to Activate Bank 3 497 if ($time - RP_chk3 < tRP) begin 498 $display ("at time %t ERROR: tRP violation during Activate bank 3", $time); 499 end 500 end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin 501 $display ("at time %t ERROR: Bank 0 is not Precharged.", $time); 502 end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin 503 $display ("at time %t ERROR: Bank 1 is not Precharged.", $time); 504 end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin 505 $display ("at time %t ERROR: Bank 2 is not Precharged.", $time); 506 end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin 507 $display ("at time %t ERROR: Bank 3 is not Precharged.", $time); 508 end 509 // Active Bank A to Active Bank B 510 if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin 511 $display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba); 512 end 513 // Load Mode Register to Active 514 if (MRD_chk < tMRD ) begin 515 $display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba); 516 end 517 // Auto Refresh to Activate 518 if (($time - RC_chk < tRC)&&Debug) begin 519 $display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba); 520 end 521 // Record variables for checking violation 522 RRD_chk = $time; 523 Previous_bank = Ba; 524 end 525 526 // Precharge Block 527 if (Prech_enable == 1'b1) begin 528 if (Addr[10] == 1'b1) begin 529 {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111; 530 {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; 531 RP_chk0 = $time; 532 RP_chk1 = $time; 533 RP_chk2 = $time; 534 RP_chk3 = $time; 535 if (Debug) $display ("at time %t PRE : Bank = ALL",$time); 536 // Activate to Precharge all banks 537 if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) || 538 ($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin 539 $display ("at time %t ERROR: tRAS violation during Precharge all bank", $time); 540 end 541 // tWR violation check for write 542 if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) || 543 ($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin 544 $display ("at time %t ERROR: tWR violation during Precharge all bank", $time); 545 end 546 end else if (Addr[10] == 1'b0) begin 547 if (Ba == 2'b00) begin 548 {Pc_b0, Act_b0} = 2'b10; 549 RP_chk0 = $time; 550 if (Debug) $display ("at time %t PRE : Bank = 0",$time); 551 // Activate to Precharge Bank 0 552 if ($time - RAS_chk0 < tRAS) begin 553 $display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time); 554 end 555 end else if (Ba == 2'b01) begin 556 {Pc_b1, Act_b1} = 2'b10; 557 RP_chk1 = $time; 558 if (Debug) $display ("at time %t PRE : Bank = 1",$time); 559 // Activate to Precharge Bank 1 560 if ($time - RAS_chk1 < tRAS) begin 561 $display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time); 562 end 563 end else if (Ba == 2'b10) begin 564 {Pc_b2, Act_b2} = 2'b10; 565 RP_chk2 = $time; 566 if (Debug) $display ("at time %t PRE : Bank = 2",$time); 567 // Activate to Precharge Bank 2 568 if ($time - RAS_chk2 < tRAS) begin 569 $display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time); 570 end 571 end else if (Ba == 2'b11) begin 572 {Pc_b3, Act_b3} = 2'b10; 573 RP_chk3 = $time; 574 if (Debug) $display ("at time %t PRE : Bank = 3",$time); 575 // Activate to Precharge Bank 3 576 if ($time - RAS_chk3 < tRAS) begin 577 $display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time); 578 end 579 end 580 // tWR violation check for write 581 if ($time - WR_chk[Ba] < tWRp) begin 582 $display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba); 583 end 584 end 585 // Terminate a Write Immediately (if same bank or all banks) 586 if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin 587 Data_in_enable = 1'b0; 588 end 589 // Precharge Command Pipeline for Read 590 if (Cas_latency_3 == 1'b1) begin 591 Command[2] = `PRECH; 592 Bank_precharge[2] = Ba; 593 A10_precharge[2] = Addr[10]; 594 end else if (Cas_latency_2 == 1'b1) begin 595 Command[1] = `PRECH; 596 Bank_precharge[1] = Ba; 597 A10_precharge[1] = Addr[10]; 598 end 599 end 600 601 // Burst terminate 602 if (Burst_term == 1'b1) begin 603 // Terminate a Write Immediately 604 if (Data_in_enable == 1'b1) begin 605 Data_in_enable = 1'b0; 606 end 607 // Terminate a Read Depend on CAS Latency 608 if (Cas_latency_3 == 1'b1) begin 609 Command[2] = `BST; 610 end else if (Cas_latency_2 == 1'b1) begin 611 Command[1] = `BST; 612 end 613 if (Debug) $display ("at time %t BST : Burst Terminate",$time); 614 end 615 616 // Read, Write, Column Latch 617 if (Read_enable == 1'b1 || Write_enable == 1'b1) begin 618 // Check to see if bank is open (ACT) 619 if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) || 620 (Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin 621 $display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba); 622 end 623 // Activate to Read or Write 624 if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD)) 625 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time); 626 if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD)) 627 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time); 628 if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD)) 629 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time); 630 if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) 631 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time); 632 // Read Command 633 if (Read_enable == 1'b1) begin 634 // CAS Latency pipeline 635 if (Cas_latency_3 == 1'b1) begin 636 if (Addr[10] == 1'b1) begin 637 Command[2] = `READ_A; 638 end else begin 639 Command[2] = `READ; 640 end 641 Col_addr[2] = Addr; 642 Bank_addr[2] = Ba; 643 end else if (Cas_latency_2 == 1'b1) begin 644 if (Addr[10] == 1'b1) begin 645 Command[1] = `READ_A; 646 end else begin 647 Command[1] = `READ; 648 end 649 Col_addr[1] = Addr; 650 Bank_addr[1] = Ba; 651 end 652 653 // Read interrupt Write (terminate Write immediately) 654 if (Data_in_enable == 1'b1) begin 655 Data_in_enable = 1'b0; 656 end 657 658 // Write Command 659 end else if (Write_enable == 1'b1) begin 660 if (Addr[10] == 1'b1) begin 661 Command[0] = `WRITE_A; 662 end else begin 663 Command[0] = `WRITE; 664 end 665 Col_addr[0] = Addr; 666 Bank_addr[0] = Ba; 667 668 // Write interrupt Write (terminate Write immediately) 669 if (Data_in_enable == 1'b1) begin 670 Data_in_enable = 1'b0; 671 end 672 673 // Write interrupt Read (terminate Read immediately) 674 if (Data_out_enable == 1'b1) begin 675 Data_out_enable = 1'b0; 676 end 677 end 678 679 // Interrupting a Write with Autoprecharge 680 if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin 681 RW_interrupt_write[Bank] = 1'b1; 682 if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank); 683 end 684 685 // Interrupting a Read with Autoprecharge 686 if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin 687 RW_interrupt_read[Bank] = 1'b1; 688 if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank); 689 end 690 691 // Read or Write with Auto Precharge 692 if (Addr[10] == 1'b1) begin 693 Auto_precharge[Ba] = 1'b1; 694 Count_precharge[Ba] = 0; 695 if (Read_enable == 1'b1) begin 696 Read_precharge[Ba] = 1'b1; 697 end else if (Write_enable == 1'b1) begin 698 Write_precharge[Ba] = 1'b1; 699 end 700 end 701 end 702 703 // Read with Auto Precharge Calculation 704 // The device start internal precharge: 705 // 1. CAS Latency - 1 cycles before last burst 706 // and 2. Meet minimum tRAS requirement 707 // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) 708 if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin 709 if ((($time - RAS_chk0 >= tRAS) && // Case 2 710 ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1 711 (Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) || 712 (Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) || 713 (Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) || 714 (RW_interrupt_read[0] == 1'b1)) begin // Case 3 715 Pc_b0 = 1'b1; 716 Act_b0 = 1'b0; 717 RP_chk0 = $time; 718 Auto_precharge[0] = 1'b0; 719 Read_precharge[0] = 1'b0; 720 RW_interrupt_read[0] = 1'b0; 721 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); 722 end 723 end 724 if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin 725 if ((($time - RAS_chk1 >= tRAS) && 726 ((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) || 727 (Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) || 728 (Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) || 729 (Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) || 730 (RW_interrupt_read[1] == 1'b1)) begin 731 Pc_b1 = 1'b1; 732 Act_b1 = 1'b0; 733 RP_chk1 = $time; 734 Auto_precharge[1] = 1'b0; 735 Read_precharge[1] = 1'b0; 736 RW_interrupt_read[1] = 1'b0; 737 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); 738 end 739 end 740 if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin 741 if ((($time - RAS_chk2 >= tRAS) && 742 ((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) || 743 (Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) || 744 (Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) || 745 (Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) || 746 (RW_interrupt_read[2] == 1'b1)) begin 747 Pc_b2 = 1'b1; 748 Act_b2 = 1'b0; 749 RP_chk2 = $time; 750 Auto_precharge[2] = 1'b0; 751 Read_precharge[2] = 1'b0; 752 RW_interrupt_read[2] = 1'b0; 753 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); 754 end 755 end 756 if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin 757 if ((($time - RAS_chk3 >= tRAS) && 758 ((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) || 759 (Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) || 760 (Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) || 761 (Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) || 762 (RW_interrupt_read[3] == 1'b1)) begin 763 Pc_b3 = 1'b1; 764 Act_b3 = 1'b0; 765 RP_chk3 = $time; 766 Auto_precharge[3] = 1'b0; 767 Read_precharge[3] = 1'b0; 768 RW_interrupt_read[3] = 1'b0; 769 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); 770 end 771 end 772 773 // Internal Precharge or Bst 774 if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks 775 if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin 776 if (Data_out_enable == 1'b1) begin 777 Data_out_enable = 1'b0; 778 end 779 end 780 end else if (Command[0] == `BST) begin // BST terminate a read to current bank 781 if (Data_out_enable == 1'b1) begin 782 Data_out_enable = 1'b0; 783 end 784 end 785 786 if (Data_out_enable == 1'b0) begin 787 Dq_reg <= #tOH {data_bits{1'bz}}; 788 end 789 790 // Detect Read or Write command 791 if (Command[0] == `READ || Command[0] == `READ_A) begin 792 Bank = Bank_addr[0]; 793 Col = Col_addr[0]; 794 Col_brst = Col_addr[0]; 795 if (Bank_addr[0] == 2'b00) begin 796 Row = B0_row_addr; 797 end else if (Bank_addr[0] == 2'b01) begin 798 Row = B1_row_addr; 799 end else if (Bank_addr[0] == 2'b10) begin 800 Row = B2_row_addr; 801 end else if (Bank_addr[0] == 2'b11) begin 802 Row = B3_row_addr; 803 end 804 Burst_counter = 0; 805 Data_in_enable = 1'b0; 806 Data_out_enable = 1'b1; 807 end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin 808 Bank = Bank_addr[0]; 809 Col = Col_addr[0]; 810 Col_brst = Col_addr[0]; 811 if (Bank_addr[0] == 2'b00) begin 812 Row = B0_row_addr; 813 end else if (Bank_addr[0] == 2'b01) begin 814 Row = B1_row_addr; 815 end else if (Bank_addr[0] == 2'b10) begin 816 Row = B2_row_addr; 817 end else if (Bank_addr[0] == 2'b11) begin 818 Row = B3_row_addr; 819 end 820 Burst_counter = 0; 821 Data_in_enable = 1'b1; 822 Data_out_enable = 1'b0; 823 end 824 825 // DQ buffer (Driver/Receiver) 826 if (Data_in_enable == 1'b1) begin // Writing Data to Memory 827 // Array buffer 828 if (Bank == 2'b00) Dq_dqm [data_bits - 1 : 0] = Bank0 [{Row, Col}]; 829 if (Bank == 2'b01) Dq_dqm [data_bits - 1 : 0] = Bank1 [{Row, Col}]; 830 if (Bank == 2'b10) Dq_dqm [data_bits - 1 : 0] = Bank2 [{Row, Col}]; 831 if (Bank == 2'b11) Dq_dqm [data_bits - 1 : 0] = Bank3 [{Row, Col}]; 832 // Dqm operation 833 if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; 834 if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8]; 835 //if (Dqm[2] == 1'b0) Dq_dqm [23 : 16] = Dq [23 : 16]; 836 // if (Dqm[3] == 1'b0) Dq_dqm [31 : 24] = Dq [31 : 24]; 837 // Write to memory 838 if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 839 if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 840 if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 841 if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 842 if (Bank == 2'b11 && Row==10'h3 && Col[7:4]==4'h4) 843 $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); 844 //$fdisplay(test_file,"bank:%h row:%h col:%h write:%h",Bank,Row,Col,Dq_dqm); 845 // Output result 846 if (Dqm == 4'b1111) begin 847 if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); 848 end else begin 849 if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm); 850 // Record tWR time and reset counter 851 WR_chk [Bank] = $time; 852 WR_counter [Bank] = 0; 853 end 854 // Advance burst counter subroutine 855 #tHZ Burst; 856 end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory 857 //$display("%h , %h, %h",Bank0,Row,Col); 858 // Array buffer 859 if (Bank == 2'b00) Dq_dqm [data_bits - 1 : 0] = Bank0 [{Row, Col}]; 860 if (Bank == 2'b01) Dq_dqm [data_bits - 1 : 0] = Bank1 [{Row, Col}]; 861 if (Bank == 2'b10) Dq_dqm [data_bits - 1 : 0] = Bank2 [{Row, Col}]; 862 if (Bank == 2'b11) Dq_dqm [data_bits - 1 : 0] = Bank3 [{Row, Col}]; 863 864 // Dqm operation 865 if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz; 866 if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz; 867 if (Dqm_reg0[2] == 1'b1) Dq_dqm [23 : 16] = 8'bz; 868 if (Dqm_reg0[3] == 1'b1) Dq_dqm [31 : 24] = 8'bz; 869 // Display result 870 Dq_reg [data_bits - 1 : 0] = #tAC Dq_dqm [data_bits - 1 : 0]; 871 if (Dqm_reg0 == 4'b1111) begin 872 if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); 873 end else begin 874 if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0); 875 end 876 // Advance burst counter subroutine 877 Burst; 878 end 879 end 880 881 // Write with Auto Precharge Calculation 882 // The device start internal precharge: 883 // 1. tWR Clock after last burst 884 // and 2. Meet minimum tRAS requirement 885 // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) 886 always @ (WR_counter[0]) begin 887 if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin 888 if ((($time - RAS_chk0 >= tRAS) && // Case 2 889 (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1 890 (Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) || 891 (Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) || 892 (Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) || 893 (RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt) 894 Auto_precharge[0] = 1'b0; 895 Write_precharge[0] = 1'b0; 896 RW_interrupt_write[0] = 1'b0; 897 #tWRa; // Wait for tWR 898 Pc_b0 = 1'b1; 899 Act_b0 = 1'b0; 900 RP_chk0 = $time; 901 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); 902 end 903 end 904 end 905 always @ (WR_counter[1]) begin 906 if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin 907 if ((($time - RAS_chk1 >= tRAS) && 908 (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || 909 (Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) || 910 (Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) || 911 (Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) || 912 (RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin 913 Auto_precharge[1] = 1'b0; 914 Write_precharge[1] = 1'b0; 915 RW_interrupt_write[1] = 1'b0; 916 #tWRa; // Wait for tWR 917 Pc_b1 = 1'b1; 918 Act_b1 = 1'b0; 919 RP_chk1 = $time; 920 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); 921 end 922 end 923 end 924 always @ (WR_counter[2]) begin 925 if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin 926 if ((($time - RAS_chk2 >= tRAS) && 927 (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || 928 (Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) || 929 (Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) || 930 (Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) || 931 (RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin 932 Auto_precharge[2] = 1'b0; 933 Write_precharge[2] = 1'b0; 934 RW_interrupt_write[2] = 1'b0; 935 #tWRa; // Wait for tWR 936 Pc_b2 = 1'b1; 937 Act_b2 = 1'b0; 938 RP_chk2 = $time; 939 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); 940 end 941 end 942 end 943 always @ (WR_counter[3]) begin 944 if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin 945 if ((($time - RAS_chk3 >= tRAS) && 946 (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || 947 (Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) || 948 (Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) || 949 (Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) || 950 (RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin 951 Auto_precharge[3] = 1'b0; 952 Write_precharge[3] = 1'b0; 953 RW_interrupt_write[3] = 1'b0; 954 #tWRa; // Wait for tWR 955 Pc_b3 = 1'b1; 956 Act_b3 = 1'b0; 957 RP_chk3 = $time; 958 if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); 959 end 960 end 961 end 962 963 task Burst; 964 begin 965 // Advance Burst Counter 966 Burst_counter = Burst_counter + 1; 967 968 // Burst Type 969 if (Mode_reg[3] == 1'b0) begin // Sequential Burst 970 Col_temp = Col + 1; 971 end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst 972 Col_temp[2] = Burst_counter[2] ^ Col_brst[2]; 973 Col_temp[1] = Burst_counter[1] ^ Col_brst[1]; 974 Col_temp[0] = Burst_counter[0] ^ Col_brst[0]; 975 end 976 977 // Burst Length 978 if (Burst_length_2) begin // Burst Length = 2 979 Col [0] = Col_temp [0]; 980 end else if (Burst_length_4) begin // Burst Length = 4 981 Col [1 : 0] = Col_temp [1 : 0]; 982 end else if (Burst_length_8) begin // Burst Length = 8 983 Col [2 : 0] = Col_temp [2 : 0]; 984 end else begin // Burst Length = FULL 985 Col = Col_temp; 986 end 987 988 // Burst Read Single Write 989 if (Write_burst_mode == 1'b1) begin 990 Data_in_enable = 1'b0; 991 end 992 993 // Data Counter 994 if (Burst_length_1 == 1'b1) begin 995 if (Burst_counter >= 1) begin 996 Data_in_enable = 1'b0; 997 Data_out_enable = 1'b0; 998 end 999 end else if (Burst_length_2 == 1'b1) begin 1000 if (Burst_counter >= 2) begin 1001 Data_in_enable = 1'b0; 1002 Data_out_enable = 1'b0; 1003 end 1004 end else if (Burst_length_4 == 1'b1) begin 1005 if (Burst_counter >= 4) begin 1006 Data_in_enable = 1'b0; 1007 Data_out_enable = 1'b0; 1008 end 1009 end else if (Burst_length_8 == 1'b1) begin 1010 if (Burst_counter >= 8) begin 1011 Data_in_enable = 1'b0; 1012 Data_out_enable = 1'b0; 1013 end 1014 end 1015 end 1016 endtask 1017 1018 //**********************将SDRAM内的数据直接输出到外部文件*******************************// 1019 1020 /* 1021 integer sdram_data,ind; 1022 1023 1024 always@(sdram_r) 1025 begin 1026 sdram_data=$fopen("sdram_data.txt"); 1027 $display("Sdram dampout begin ",sdram_data); 1028 // $fdisplay(sdram_data,"Bank0:"); 1029 for(ind=0;ind<=mem_sizes;ind=ind+1) 1030 $fdisplay(sdram_data,"%h %b",ind,Bank0[ind]); 1031 // $fdisplay(sdram_data,"Bank1:"); 1032 for(ind=0;ind<=mem_sizes;ind=ind+1) 1033 $fdisplay(sdram_data,"%h %b",ind,Bank1[ind]); 1034 // $fdisplay(sdram_data,"Bank2:"); 1035 for(ind=0;ind<=mem_sizes;ind=ind+1) 1036 $fdisplay(sdram_data,"%h %b",ind,Bank2[ind]); 1037 // $fdisplay(sdram_data,"Bank3:"); 1038 for(ind=0;ind<=mem_sizes;ind=ind+1) 1039 $fdisplay(sdram_data,"%h %b",ind,Bank3[ind]); 1040 1041 $fclose("sdram_data.txt"); 1042 //->compare; 1043 end 1044 */ 1045 integer sdram_data,sdram_mem; 1046 reg [23:0] aa,cc; 1047 reg [18:0] bb,ee; 1048 1049 always@(sdram_r) 1050 begin 1051 $display("Sdram dampout begin ",$realtime); 1052 sdram_data=$fopen("sdram_data.txt"); 1053 for(aa=0;aa<4*(mem_sizes+1);aa=aa+1) 1054 begin 1055 bb=aa[18:0]; 1056 if(aa<=mem_sizes) 1057 $fdisplay(sdram_data,"%0d %0h",aa,Bank0[bb]); 1058 else if(aa<=2*mem_sizes+1) 1059 $fdisplay(sdram_data,"%0d %0h",aa,Bank1[bb]); 1060 else if(aa<=3*mem_sizes+2) 1061 $fdisplay(sdram_data,"%0d %0h",aa,Bank2[bb]); 1062 else 1063 $fdisplay(sdram_data,"%0d %0h",aa,Bank3[bb]); 1064 end 1065 $fclose("sdram_data.txt"); 1066 1067 sdram_mem=$fopen("sdram_mem.txt"); 1068 for(cc=0;cc<4*(mem_sizes+1);cc=cc+1) 1069 begin 1070 ee=cc[18:0]; 1071 if(cc<=mem_sizes) 1072 $fdisplay(sdram_mem,"%0h",Bank0[ee]); 1073 else if(cc<=2*mem_sizes+1) 1074 $fdisplay(sdram_mem,"%0h",Bank1[ee]); 1075 else if(cc<=3*mem_sizes+2) 1076 $fdisplay(sdram_mem,"%0h",Bank2[ee]); 1077 else 1078 $fdisplay(sdram_mem,"%0h",Bank3[ee]); 1079 end 1080 $fclose("sdram_mem.txt"); 1081 1082 end 1083 1084 1085 1086 // // Timing Parameters for -75 (PC133) and CAS Latency = 2 1087 // specify 1088 // specparam 1089 //// tAH = 0.8, // Addr, Ba Hold Time 1090 //// tAS = 1.5, // Addr, Ba Setup Time 1091 //// tCH = 2.5, // Clock High-Level Width 1092 //// tCL = 2.5, // Clock Low-Level Width 1093 ////// tCK = 10.0, // Clock Cycle Time 100mhz 1094 ////// tCK = 7.5, // Clock Cycle Time 133mhz 1095 //// tCK = 7, // Clock Cycle Time 143mhz 1096 //// tDH = 0.8, // Data-in Hold Time 1097 //// tDS = 1.5, // Data-in Setup Time 1098 //// tCKH = 0.8, // CKE Hold Time 1099 //// tCKS = 1.5, // CKE Setup Time 1100 //// tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time 1101 //// tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time 1102 // tAH = 1, // Addr, Ba Hold Time 1103 // tAS = 1.5, // Addr, Ba Setup Time 1104 // tCH = 1, // Clock High-Level Width 1105 // tCL = 3, // Clock Low-Level Width 1106 //// tCK = 10.0, // Clock Cycle Time 100mhz 1107 //// tCK = 7.5, // Clock Cycle Time 133mhz 1108 // tCK = 7, // Clock Cycle Time 143mhz 1109 // tDH = 1, // Data-in Hold Time 1110 // tDS = 2, // Data-in Setup Time 1111 // tCKH = 1, // CKE Hold Time 1112 // tCKS = 2, // CKE Setup Time 1113 // tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time 1114 // tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time 1115 // $width (posedge Clk, tCH); 1116 // $width (negedge Clk, tCL); 1117 // $period (negedge Clk, tCK); 1118 // $period (posedge Clk, tCK); 1119 // $setuphold(posedge Clk, Cke, tCKS, tCKH); 1120 // $setuphold(posedge Clk, Cs_n, tCMS, tCMH); 1121 // $setuphold(posedge Clk, Cas_n, tCMS, tCMH); 1122 // $setuphold(posedge Clk, Ras_n, tCMS, tCMH); 1123 // $setuphold(posedge Clk, We_n, tCMS, tCMH); 1124 // $setuphold(posedge Clk, Addr, tAS, tAH); 1125 // $setuphold(posedge Clk, Ba, tAS, tAH); 1126 // $setuphold(posedge Clk, Dqm, tCMS, tCMH); 1127 // $setuphold(posedge Dq_chk, Dq, tDS, tDH); 1128 // endspecify 1129 1130 endmodule
Modelsim仿真结果:


浙公网安备 33010602011771号