2018/7/26
受教于邓堪文老师,开始真真学习控制sdram
由于自己买的sdram模块是256的,原来老师的是128,所以边学边改,不知道最后好不好使,但是我有信心
一.sdram的初始化
sdram介绍啥的就不用了,上来就是干,简单粗暴。
1.下面是引脚说明,看不懂自己可以用百度翻译,需要注意的是红框内的地址引脚和行列地址是复用的,A0~A12是行地址,A0~8是列地址
简单说一下SDRAM的容量计算:数据位宽 *行地址*列地址*bank数,我们用的256有4个bank,就是:16*8192*512*4
2.我的fpga是50m时钟,20ns一个周期,下图是初始化的时序图
sdram上电要延时至少100us,我们是延时200us,然后precharge(预充电)命令,隔tRP时间也就是一个时钟周期20ns进行第一次auto_refresh(自刷新),再隔tRC时间也就是四个时钟周期进行第二次auto_refresh命令,
又tRC时间进行mode_register(模式寄存器配置)。期间的NOP是空操作命令。还有就是这几个时间要看自己使用sdram的datasheet
3.上面说的命令也是要去datasheet手册去找,对应CS,RAS,CAS,WE的操作
4.模式配置对应datasheet ,根据红框addr:0_0000_0010_0010
5.再来一张时序图
6.该上源码了,应该没啥看不懂的吧
`timescale 1ns/1ns module tb_sdram_top; reg sclk ; reg s_rst_n ; //---------------------------------------------------------- wire sdram_clk ; wire sdram_cke ; wire sdram_cs_n ; wire sdram_cas_n ; wire sdram_ras_n ; wire sdram_we_n ; :] sdram_bank ; :] sdram_addr ; :] sdram_dqm ; :] sdram_dq ; initial begin sclk = ; s_rst_n <= ; # s_rst_n <= ; end sclk = ~sclk; sdram_top sdram_top_inst( //system signals .sclk (sclk ), .s_rst_n (s_rst_n ), //SDRAM Interfaces .sdram_clk (sdram_clk ), .sdram_cke (sdram_cke ), .sdram_cs_n (sdram_cs_n ), .sdram_cas_n (sdram_cas_n ), .sdram_ras_n (sdram_ras_n ), .sdram_we_n (sdram_we_n ), .sdram_bank (sdram_bank ), .sdram_addr (sdram_addr ), .sdram_dqm (sdram_dqm ), .sdram_dq (sdram_dq ) ); sdram_model_plus sdram_model_plus_inst( .Dq (sdram_dq ), .Addr (sdram_addr ), .Ba (sdram_bank ), .Clk (sdram_clk ), .Cke (sdram_cke ), .Cs_n (sdram_cs_n ), .Ras_n (sdram_ras_n ), .Cas_n (sdram_cas_n ), .We_n (sdram_we_n ), .Dqm (sdram_dqm ), .Debug ('b1 ) ); endmodule
tb_sdram_top
module sdram_ini( //systejm signal input sclk , input s_rst_n , //others :] cmd_reg , :] sdram_addr , output flag_ini_end ); //==============================================================================\ //*********************Define Parameter and Internal Signal ******************** //==============================================================================/ ; //SDRAM Command 'b0111 ; 'b0010 ; 'b0001 ; 'b0000 ; :] cnt_200us ; wire flag_200us ; :] cnt_cmd ; //=============================================================================\ //********************** Main Code *************************************** //=============================================================================/ always @(posedge sclk or negedge s_rst_n) begin 'b0) cnt_200us <= 'd0; 'b0) cnt_200us <= cnt_200us + 'b1; end always @(posedge sclk or negedge s_rst_n) begin 'b0) cnt_cmd <= 'd0; 'b1 && flag_ini_end == 1'b0) cnt_cmd <= cnt_cmd + 'b1; end //cmd_reg always @(posedge sclk or negedge s_rst_n ) begin 'b0) cmd_reg <= NOP; 'b1) case(cnt_cmd) : cmd_reg <= PRE ; : cmd_reg <= AREF ; : cmd_reg <= AREF ; : cmd_reg <= MSET ; default : cmd_reg <= NOP ; endcase end 'b0; 'b0_0000_0011_0010 : 13'b0_0100_0000_0000; 'b1 : 1'b0; endmodule
sdram_init
module sdram_top( //system signals input sclk , input s_rst_n , //SDRAM Interfaces output wire sdram_clk , output wire sdram_cke , output wire sdram_cs_n , output wire sdram_cas_n , output wire sdram_ras_n , output wire sdram_we_n , :] sdram_bank , :] sdram_addr , :] sdram_dqm , :] sdram_dq ); //==============================================================================\ //*********************Define Parameter and Internal Signal ******************** //==============================================================================/ //init module wire flag_ini_end ; :] init_cmd ; :] init_addr ; //=============================================================================\ //********************** Main Code *************************************** //=============================================================================/ 'b1; assign sdram_addr = init_addr; assign {sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n} = init_cmd ; 'd0; assign sdram_clk = ~sclk; sdram_ini sdram_ini_inst( //systejm signal .sclk (sclk ), .s_rst_n (s_rst_n ), //others .cmd_reg (init_cmd ), .sdram_addr (init_addr ), .flag_ini_end (flag_ini_end ) ); endmodule
sdram_top
这用了一个sdram仿真模型,堪文老师是128的,我的256的不能用,但是我改好了
/*************************************************************************************** 作者: 李晟 2003-08-27 V0.1 李晟 添加内存模块倒空功能,在外部需要创建事件:sdram_r ,本SDRAM的内容将会按Bank 顺序damp out 至文件 sdram_data.txt 中 ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/ //2004-03-04 陈乃奎 修改原程序中将BANK的数据转存入TXT文件的格式 //2004-03-16 陈乃奎 修改SDRAM 的初始化数据 //2004/04/06 陈乃奎 将SDRAM的操作命令以字符形式表示,以便用MODELSIM监视 //2004/04/19 陈乃奎 修改参数 parameter tAC = 8; //2010/09/17 罗瑶 修改sdram的大小,数据位宽,dqm宽度; /**************************************************************************************** * * File Name: sdram_model.V * Version: 0.0f * Date: July 8th, 1999 * Model: BUS Functional * Simulator: Model Technology (PC version 5.2e PE) * * Dependencies: None * * Author: Son P. Huynh * Email: [email protected] * Phone: (208) 368-3825 * Company: Micron Technology, Inc. * Model: sdram_model (1Meg x 16 x 4 Banks) * * Description: 64Mb SDRAM Verilog model * * Limitation: - Doesn't check for 4096 cycle refresh * * Note: - Set simulator resolution to "ps" accuracy * - Set Debug = 0 to disable $display messages * * Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY * WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR * A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. * * Copyright ?1998 Micron Semiconductor Products, Inc. * All rights researved * * Rev Author Phone Date Changes * ---- ---------------------------- ---------- --------------------------------------- * 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto) * Micron Technology Inc. - Fix tWR = 15 ns (Manual) * - Fix tRP (Autoprecharge to AutoRefresh) * * 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e) * Micron Technology Inc. ****************************************************************************************/ `timescale 1ns / 100ps module sdram_model_plus (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm,Debug); ; ; ; ** -;//1 Meg : ] Dq; : ] Addr; : ] Ba; input Clk; input Cke; input Cs_n; input Ras_n; input Cas_n; input We_n; : ] Dqm; //高低各8bit //added by xzli input Debug; : ] Bank0 [ : mem_sizes];//存储器类型数据 : ] Bank1 [ : mem_sizes]; : ] Bank2 [ : mem_sizes]; : ] Bank3 [ : mem_sizes]; : ] Bank_addr [ : ]; // Bank Address Pipeline : ] Col_addr [ : ]; // Column Address Pipeline : ] Command [ : ]; // Command Operation Pipeline : ] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline : ] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; : ] Mode_reg; : ] Dq_reg, Dq_dqm; : ] Col_temp, Burst_counter; reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge : ] Bank_precharge [ : ]; // Precharge Command : ]; // Addr[10] = 1 (All banks) : ]; // RW AutoPrecharge (Bank) : ]; // R AutoPrecharge : ]; // W AutoPrecharge : ]; // RW AutoPrecharge (Counter) : ]; // RW Interrupt Read with Auto Precharge : ]; // RW Interrupt Write with Auto Precharge reg Data_in_enable; reg Data_out_enable; : ] Bank, Previous_bank; : ] Row; : ] Col, Col_brst; // Internal system clock reg CkeZ, Sys_clk; :] dd; // Commands Decode wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n; wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; // Burst Length Decode ] & ~Mode_reg[] & ~Mode_reg[]; ] & ~Mode_reg[] & Mode_reg[]; ] & Mode_reg[] & ~Mode_reg[]; ] & Mode_reg[] & Mode_reg[]; // CAS Latency Decode ] & Mode_reg[] & ~Mode_reg[]; ] & Mode_reg[] & Mode_reg[]; // Write Burst Mode ]; wire Debug; // Debug messages : 1 = On; 0 = Off wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ :] mem_d; event sdram_r,sdram_w,compare; assign Dq = Dq_reg; // DQ buffer // Commands Operation `define ACT `define NOP `define READ `define READ_A `define WRITE `define WRITE_A `define PRECH `define A_REF `define BST `define LMR // // Timing Parameters for -75 (PC133) and CAS Latency = 2 // parameter tAC = 8; //test 6.5 // parameter tHZ = 7.0; // parameter tOH = 2.7; // parameter tMRD = 2.0; // 2 Clk Cycles // parameter tRAS = 44.0; // parameter tRC = 66.0; // parameter tRCD = 20.0; // parameter tRP = 20.0; // parameter tRRD = 15.0; // parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) // parameter tWRp = 0.0; // A2 Version - Precharge mode only (15 ns) // Timing Parameters for -7 (PC143) and CAS Latency = 3 parameter tAC = 6.5; //test 6.5 parameter tHZ = 5.5; ; parameter tMRD = 2.0; // 2 Clk Cycles parameter tRAS = 48.0; parameter tRC = 70.0; parameter tRCD = 20.0; parameter tRP = 20.0; parameter tRRD = 14.0; parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) parameter tWRp = 0.0; // A2 Version - Precharge mode only (15 ns) // Timing Check variable integer MRD_chk; : ]; : ]; time RC_chk, RRD_chk; time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; time RP_chk0, RP_chk1, RP_chk2, RP_chk3; integer test_file; //*****display the command of the sdram************************************** 'b0000; 'b0001; 'b0011; 'b0010; 'b0010; 'b0100; 'b0100; 'b0101; 'b0101; 'b0110; 'b0111; 'b1111; :] sdram_control; reg cke_temp; *:] sdram_command; always@(posedge Clk) cke_temp<=Cke; assign sdram_control={Cs_n,Ras_n,Cas_n,We_n}; always@(sdram_control or cke_temp) begin case(sdram_control) Mode_Reg_Set: sdram_command<="Mode_Reg_Set"; Auto_Refresh: sdram_command<="Auto_Refresh"; Row_Active: sdram_command<="Row_Active"; Pre_Charge: sdram_command<="Pre_Charge"; Burst_Stop: sdram_command<="Burst_Stop"; Dsel: sdram_command<="Dsel"; Write: ) sdram_command<="Write"; else sdram_command<="Write_suspend"; Read: ) sdram_command<="Read"; else sdram_command<="Read_suspend"; Nop: ) sdram_command<="Nop"; else sdram_command<="Self_refresh"; default: sdram_command<="Power_down"; endcase end //***************************************************** initial begin //test_file=$fopen("test_file.txt"); end initial begin Dq_reg = {data_bits{'bz}}; {Data_in_enable, Data_out_enable} = ; {Act_b0, Act_b1, Act_b2, Act_b3} = 'b0000; {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 'b0000; {WR_chk[], WR_chk[], WR_chk[], WR_chk[]} = ; {WR_counter[], WR_counter[], WR_counter[], WR_counter[]} = ; {RW_interrupt_read[], RW_interrupt_read[], RW_interrupt_read[], RW_interrupt_read[]} = ; {RW_interrupt_write[], RW_interrupt_write[], RW_interrupt_write[], RW_interrupt_write[]} = ; {MRD_chk, RC_chk, RRD_chk} = ; {RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = ; {RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = ; {RP_chk0, RP_chk1, RP_chk2, RP_chk3} = ; $timeformat (-, , ); //$readmemh("bank0.txt", Bank0); //$readmemh("bank1.txt", Bank1); //$readmemh("bank2.txt", Bank2); //$readmemh("bank3.txt", Bank3); /* for(dd=0;dd<=mem_sizes;dd=dd+1) begin Bank0[dd]=dd[data_bits - 1 : 0]; Bank1[dd]=dd[data_bits - 1 : 0]+1; Bank2[dd]=dd[data_bits - 1 : 0]+2; Bank3[dd]=dd[data_bits - 1 : 0]+3; end */ initial_sdram(); end task initial_sdram; input data_sign; :] data_sign; ;dd<=mem_sizes;dd=dd+) begin mem_d = {data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign}; ) begin Bank0[dd]=mem_d[:]; Bank1[dd]=mem_d[:]; Bank2[dd]=mem_d[:]; Bank3[dd]=mem_d[:]; end ) begin Bank0[dd]=mem_d[:]; Bank1[dd]=mem_d[:]; Bank2[dd]=mem_d[:]; Bank3[dd]=mem_d[:]; end end endtask // System clock generator always begin @(posedge Clk) begin Sys_clk = CkeZ; CkeZ = Cke; end @(negedge Clk) begin Sys_clk = 'b0; end end always @ (posedge Sys_clk) begin // Internal Commamd Pipelined Command[] = Command[]; Command[] = Command[]; Command[] = Command[]; Command[] = `NOP; Col_addr[] = Col_addr[]; Col_addr[] = Col_addr[]; Col_addr[] = Col_addr[]; Col_addr[] = {col_bits{'b0}}; Bank_addr[] = Bank_addr[]; Bank_addr[] = Bank_addr[]; Bank_addr[] = Bank_addr[]; Bank_addr[] = 'b0; Bank_precharge[] = Bank_precharge[]; Bank_precharge[] = Bank_precharge[]; Bank_precharge[] = Bank_precharge[]; Bank_precharge[] = 'b0; A10_precharge[] = A10_precharge[]; A10_precharge[] = A10_precharge[]; A10_precharge[] = A10_precharge[]; A10_precharge[] = 'b0; // Dqm pipeline for Read Dqm_reg0 = Dqm_reg1; Dqm_reg1 = Dqm; // Read or Write with Auto Precharge Counter ] == 'b1) begin Count_precharge[] = Count_precharge[] + ; end ] == 'b1) begin Count_precharge[] = Count_precharge[] + ; end ] == 'b1) begin Count_precharge[] = Count_precharge[] + ; end ] == 'b1) begin Count_precharge[] = Count_precharge[] + ; end // tMRD Counter MRD_chk = MRD_chk + ; // tWR Counter for Write WR_counter[] = WR_counter[] + ; WR_counter[] = WR_counter[] + ; WR_counter[] = WR_counter[] + ; WR_counter[] = WR_counter[] + ; // Auto Refresh 'b1) begin if (Debug) $display ("at time %t AREF : Auto Refresh", $time); // Auto Refresh to Auto Refresh if (($time - RC_chk < tRC)&&Debug) begin $display ("at time %t ERROR: tRC violation during Auto Refresh", $time); end // Precharge to Auto Refresh if (($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP)&&Debug) begin $display ("at time %t ERROR: tRP violation during Auto Refresh", $time); end // Precharge to Refresh 'b0 || Pc_b3 == 1'b0) begin $display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time); end // Record Current tRC time RC_chk = $time; end // Load Mode Register 'b1) begin // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode 'b1 && Pc_b3 == 1'b1) begin Mode_reg = Addr; if (Debug) begin $display ("at time %t LMR : Load Mode Register", $time); // CAS Latency : ] == 'b010) $display (" CAS Latency = 2"); : ] == 'b011) $display (" CAS Latency = 3"); else $display (" CAS Latency = Reserved"); // Burst Length : ] == 'b000) $display (" Burst Length = 1"); : ] == 'b001) $display (" Burst Length = 2"); : ] == 'b010) $display (" Burst Length = 4"); : ] == 'b011) $display (" Burst Length = 8"); : ] == 'b0111) $display (" Burst Length = Full"); else $display (" Burst Length = Reserved"); // Burst Type ] == 'b0) $display (" Burst Type = Sequential"); ] == 'b1) $display (" Burst Type = Interleaved"); else $display (" Burst Type = Reserved"); // Write Burst Mode ] == 'b0) $display (" Write Burst Mode = Programmed Burst Length"); ] == 'b1) $display (" Write Burst Mode = Single Location Access"); else $display (" Write Burst Mode = Reserved"); end end else begin $display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); end // REF to LMR if ($time - RC_chk < tRC) begin $display ("at time %t ERROR: tRC violation during Load Mode Register", $time); end // LMR to LMR if (MRD_chk < tMRD) begin $display ("at time %t ERROR: tMRD violation during Load Mode Register", $time); end MRD_chk = ; end // Active Block (Latch Bank Address and Row Address) 'b1) begin 'b00 && Pc_b0 == 1'b1) begin {Act_b0, Pc_b0} = 'b10; B0_row_addr = Addr [addr_bits - : ]; RCD_chk0 = $time; RAS_chk0 = $time; if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr); // Precharge to Activate Bank 0 if ($time - RP_chk0 < tRP) begin $display ("at time %t ERROR: tRP violation during Activate bank 0", $time); end 'b01 && Pc_b1 == 1'b1) begin {Act_b1, Pc_b1} = 'b10; B1_row_addr = Addr [addr_bits - : ]; RCD_chk1 = $time; RAS_chk1 = $time; if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr); // Precharge to Activate Bank 1 if ($time - RP_chk1 < tRP) begin $display ("at time %t ERROR: tRP violation during Activate bank 1", $time); end 'b10 && Pc_b2 == 1'b1) begin {Act_b2, Pc_b2} = 'b10; B2_row_addr = Addr [addr_bits - : ]; RCD_chk2 = $time; RAS_chk2 = $time; if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr); // Precharge to Activate Bank 2 if ($time - RP_chk2 < tRP) begin $display ("at time %t ERROR: tRP violation during Activate bank 2", $time); end 'b11 && Pc_b3 == 1'b1) begin {Act_b3, Pc_b3} = 'b10; B3_row_addr = Addr [addr_bits - : ]; RCD_chk3 = $time; RAS_chk3 = $time; if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr); // Precharge to Activate Bank 3 if ($time - RP_chk3 < tRP) begin $display ("at time %t ERROR: tRP violation during Activate bank 3", $time); end 'b00 && Pc_b0 == 1'b0) begin $display ("at time %t ERROR: Bank 0 is not Precharged.", $time); 'b01 && Pc_b1 == 1'b0) begin $display ("at time %t ERROR: Bank 1 is not Precharged.", $time); 'b10 && Pc_b2 == 1'b0) begin $display ("at time %t ERROR: Bank 2 is not Precharged.", $time); 'b11 && Pc_b3 == 1'b0) begin $display ("at time %t ERROR: Bank 3 is not Precharged.", $time); end // Active Bank A to Active Bank B if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin $display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba); end // Load Mode Register to Active if (MRD_chk < tMRD ) begin $display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba); end // Auto Refresh to Activate if (($time - RC_chk < tRC)&&Debug) begin $display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba); end // Record variables for checking violation RRD_chk = $time; Previous_bank = Ba; end // Precharge Block 'b1) begin ] == 'b1) begin {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 'b1111; {Act_b0, Act_b1, Act_b2, Act_b3} = 'b0000; RP_chk0 = $time; RP_chk1 = $time; RP_chk2 = $time; RP_chk3 = $time; if (Debug) $display ("at time %t PRE : Bank = ALL",$time); // Activate to Precharge all banks if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) || ($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin $display ("at time %t ERROR: tRAS violation during Precharge all bank", $time); end // tWR violation check for write ] < tWRp) || ($] < tWRp) || ($] < tWRp) || ($] < tWRp)) begin $display ("at time %t ERROR: tWR violation during Precharge all bank", $time); end ] == 'b0) begin 'b00) begin {Pc_b0, Act_b0} = 'b10; RP_chk0 = $time; if (Debug) $display ("at time %t PRE : Bank = 0",$time); // Activate to Precharge Bank 0 if ($time - RAS_chk0 < tRAS) begin $display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time); end 'b01) begin {Pc_b1, Act_b1} = 'b10; RP_chk1 = $time; if (Debug) $display ("at time %t PRE : Bank = 1",$time); // Activate to Precharge Bank 1 if ($time - RAS_chk1 < tRAS) begin $display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time); end 'b10) begin {Pc_b2, Act_b2} = 'b10; RP_chk2 = $time; if (Debug) $display ("at time %t PRE : Bank = 2",$time); // Activate to Precharge Bank 2 if ($time - RAS_chk2 < tRAS) begin $display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time); end 'b11) begin {Pc_b3, Act_b3} = 'b10; RP_chk3 = $time; if (Debug) $display ("at time %t PRE : Bank = 3",$time); // Activate to Precharge Bank 3 if ($time - RAS_chk3 < tRAS) begin $display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time); end end // tWR violation check for write if ($time - WR_chk[Ba] < tWRp) begin $display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba); end end // Terminate a Write Immediately (if same bank or all banks) 'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin Data_in_enable = 'b0; end // Precharge Command Pipeline for Read 'b1) begin Command[] = `PRECH; Bank_precharge[] = Ba; A10_precharge[] = Addr[]; 'b1) begin Command[] = `PRECH; Bank_precharge[] = Ba; A10_precharge[] = Addr[]; end end // Burst terminate 'b1) begin // Terminate a Write Immediately 'b1) begin Data_in_enable = 'b0; end // Terminate a Read Depend on CAS Latency 'b1) begin Command[] = `BST; 'b1) begin Command[] = `BST; end if (Debug) $display ("at time %t BST : Burst Terminate",$time); end // Read, Write, Column Latch 'b1 || Write_enable == 1'b1) begin // Check to see if bank is open (ACT) 'b01 && Pc_b1 == 1'b1) || (Ba == 'b11 && Pc_b3 == 1'b1)) begin $display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba); end // Activate to Read or Write 'b00) && ($time - RCD_chk0 < tRCD)) $display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time); 'b01) && ($time - RCD_chk1 < tRCD)) $display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time); 'b10) && ($time - RCD_chk2 < tRCD)) $display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time); 'b11) && ($time - RCD_chk3 < tRCD)) $display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time); // Read Command 'b1) begin // CAS Latency pipeline 'b1) begin ] == 'b1) begin Command[] = `READ_A; end else begin Command[] = `READ; end Col_addr[] = Addr; Bank_addr[] = Ba; 'b1) begin ] == 'b1) begin Command[] = `READ_A; end else begin Command[] = `READ; end Col_addr[] = Addr; Bank_addr[] = Ba; end // Read interrupt Write (terminate Write immediately) 'b1) begin Data_in_enable = 'b0; end // Write Command 'b1) begin ] == 'b1) begin Command[] = `WRITE_A; end else begin Command[] = `WRITE; end Col_addr[] = Addr; Bank_addr[] = Ba; // Write interrupt Write (terminate Write immediately) 'b1) begin Data_in_enable = 'b0; end // Write interrupt Read (terminate Read immediately) 'b1) begin Data_out_enable = 'b0; end end // Interrupting a Write with Autoprecharge 'b1 && Write_precharge[Bank] == 1'b1) begin RW_interrupt_write[Bank] = 'b1; if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank); end // Interrupting a Read with Autoprecharge 'b1 && Read_precharge[Bank] == 1'b1) begin RW_interrupt_read[Bank] = 'b1; if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank); end // Read or Write with Auto Precharge ] == 'b1) begin Auto_precharge[Ba] = 'b1; Count_precharge[Ba] = ; 'b1) begin Read_precharge[Ba] = 'b1; 'b1) begin Write_precharge[Ba] = 'b1; end end end // Read with Auto Precharge Calculation // The device start internal precharge: // 1. CAS Latency - 1 cycles before last burst // and 2. Meet minimum tRAS requirement // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) ] == 'b1) && (Read_precharge[0] == 1'b1)) begin if ((($time - RAS_chk0 >= tRAS) && // Case 2 ((Burst_length_1 == 'b1 && Count_precharge[0] >= 1) || // Case 1 (Burst_length_2 == 'b1 && Count_precharge[0] >= 2) || (Burst_length_4 == 'b1 && Count_precharge[0] >= 4) || (Burst_length_8 == 'b1 && Count_precharge[0] >= 8))) || (RW_interrupt_read[] == 'b1)) begin // Case 3 Pc_b0 = 'b1; Act_b0 = 'b0; RP_chk0 = $time; Auto_precharge[] = 'b0; Read_precharge[] = 'b0; RW_interrupt_read[] = 'b0; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); end end ] == 'b1) && (Read_precharge[1] == 1'b1)) begin if ((($time - RAS_chk1 >= tRAS) && ((Burst_length_1 == 'b1 && Count_precharge[1] >= 1) || (Burst_length_2 == 'b1 && Count_precharge[1] >= 2) || (Burst_length_4 == 'b1 && Count_precharge[1] >= 4) || (Burst_length_8 == 'b1 && Count_precharge[1] >= 8))) || (RW_interrupt_read[] == 'b1)) begin Pc_b1 = 'b1; Act_b1 = 'b0; RP_chk1 = $time; Auto_precharge[] = 'b0; Read_precharge[] = 'b0; RW_interrupt_read[] = 'b0; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); end end ] == 'b1) && (Read_precharge[2] == 1'b1)) begin if ((($time - RAS_chk2 >= tRAS) && ((Burst_length_1 == 'b1 && Count_precharge[2] >= 1) || (Burst_length_2 == 'b1 && Count_precharge[2] >= 2) || (Burst_length_4 == 'b1 && Count_precharge[2] >= 4) || (Burst_length_8 == 'b1 && Count_precharge[2] >= 8))) || (RW_interrupt_read[] == 'b1)) begin Pc_b2 = 'b1; Act_b2 = 'b0; RP_chk2 = $time; Auto_precharge[] = 'b0; Read_precharge[] = 'b0; RW_interrupt_read[] = 'b0; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); end end ] == 'b1) && (Read_precharge[3] == 1'b1)) begin if ((($time - RAS_chk3 >= tRAS) && ((Burst_length_1 == 'b1 && Count_precharge[3] >= 1) || (Burst_length_2 == 'b1 && Count_precharge[3] >= 2) || (Burst_length_4 == 'b1 && Count_precharge[3] >= 4) || (Burst_length_8 == 'b1 && Count_precharge[3] >= 8))) || (RW_interrupt_read[] == 'b1)) begin Pc_b3 = 'b1; Act_b3 = 'b0; RP_chk3 = $time; Auto_precharge[] = 'b0; Read_precharge[] = 'b0; RW_interrupt_read[] = 'b0; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); end end // Internal Precharge or Bst ] == `PRECH) begin // Precharge terminate a read with same bank or all banks ] == Bank || A10_precharge[] == 'b1) begin 'b1) begin Data_out_enable = 'b0; end end ] == `BST) begin // BST terminate a read to current bank 'b1) begin Data_out_enable = 'b0; end end 'b0) begin Dq_reg <= #tOH {data_bits{'bz}}; end // Detect Read or Write command ] == `READ || Command[] == `READ_A) begin Bank = Bank_addr[]; Col = Col_addr[]; Col_brst = Col_addr[]; ] == 'b00) begin Row = B0_row_addr; ] == 'b01) begin Row = B1_row_addr; ] == 'b10) begin Row = B2_row_addr; ] == 'b11) begin Row = B3_row_addr; end Burst_counter = ; Data_in_enable = 'b0; Data_out_enable = 'b1; ] == `WRITE || Command[] == `WRITE_A) begin Bank = Bank_addr[]; Col = Col_addr[]; Col_brst = Col_addr[]; ] == 'b00) begin Row = B0_row_addr; ] == 'b01) begin Row = B1_row_addr; ] == 'b10) begin Row = B2_row_addr; ] == 'b11) begin Row = B3_row_addr; end Burst_counter = ; Data_in_enable = 'b1; Data_out_enable = 'b0; end // DQ buffer (Driver/Receiver) 'b1) begin // Writing Data to Memory // Array buffer 'b00) Dq_dqm [data_bits - 1 : 0] = Bank0 [{Row, Col}]; 'b01) Dq_dqm [data_bits - 1 : 0] = Bank1 [{Row, Col}]; 'b10) Dq_dqm [data_bits - 1 : 0] = Bank2 [{Row, Col}]; 'b11) Dq_dqm [data_bits - 1 : 0] = Bank3 [{Row, Col}]; // Dqm operation ] == 'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; ] == 'b0) Dq_dqm [15 : 8] = Dq [15 : 8]; //if (Dqm[2] == 1'b0) Dq_dqm [23 : 16] = Dq [23 : 16]; // if (Dqm[3] == 1'b0) Dq_dqm [31 : 24] = Dq [31 : 24]; // Write to memory 'b00) Bank0 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 'b01) Bank1 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 'b10) Bank2 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; 'b11) Bank3 [{Row, Col}] = Dq_dqm [data_bits - 1 : 0]; :]=='h4) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); //$fdisplay(test_file,"bank:%h row:%h col:%h write:%h",Bank,Row,Col,Dq_dqm); // Output result 'b1111) begin if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); end else begin if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm); // Record tWR time and reset counter WR_chk [Bank] = $time; WR_counter [Bank] = ; end // Advance burst counter subroutine #tHZ Burst; 'b1) begin // Reading Data from Memory //$display("%h , %h, %h",Bank0,Row,Col); // Array buffer 'b00) Dq_dqm [data_bits - 1 : 0] = Bank0 [{Row, Col}]; 'b01) Dq_dqm [data_bits - 1 : 0] = Bank1 [{Row, Col}]; 'b10) Dq_dqm [data_bits - 1 : 0] = Bank2 [{Row, Col}]; 'b11) Dq_dqm [data_bits - 1 : 0] = Bank3 [{Row, Col}]; // Dqm operation ] == 'b1) Dq_dqm [ 7 : 0] = 8'bz; ] == 'b1) Dq_dqm [15 : 8] = 8'bz; ] == 'b1) Dq_dqm [23 : 16] = 8'bz; ] == 'b1) Dq_dqm [31 : 24] = 8'bz; // Display result Dq_reg [data_bits - : ] = #tAC Dq_dqm [data_bits - : ]; 'b1111) begin if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); end else begin 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); end // Advance burst counter subroutine Burst; end end // Write with Auto Precharge Calculation // The device start internal precharge: // 1. tWR Clock after last burst // and 2. Meet minimum tRAS requirement // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) ]) begin ] == 'b1) && (Write_precharge[0] == 1'b1)) begin if ((($time - RAS_chk0 >= tRAS) && // Case 2 (((Burst_length_1 == ] >= ) || // Case 1 (Burst_length_2 == 'b1 && Count_precharge [0] >= 2) || (Burst_length_4 == 'b1 && Count_precharge [0] >= 4) || (Burst_length_8 == 'b1 && Count_precharge [0] >= 8))) || (RW_interrupt_write[] == 'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt) Auto_precharge[] = 'b0; Write_precharge[] = 'b0; RW_interrupt_write[] = 'b0; #tWRa; // Wait for tWR Pc_b0 = 'b1; Act_b0 = 'b0; RP_chk0 = $time; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); end end end ]) begin ] == 'b1) && (Write_precharge[1] == 1'b1)) begin if ((($time - RAS_chk1 >= tRAS) && (((Burst_length_1 == ] >= ) || (Burst_length_2 == 'b1 && Count_precharge [1] >= 2) || (Burst_length_4 == 'b1 && Count_precharge [1] >= 4) || (Burst_length_8 == 'b1 && Count_precharge [1] >= 8))) || (RW_interrupt_write[] == 'b1 && WR_counter[1] >= 2)) begin Auto_precharge[] = 'b0; Write_precharge[] = 'b0; RW_interrupt_write[] = 'b0; #tWRa; // Wait for tWR Pc_b1 = 'b1; Act_b1 = 'b0; RP_chk1 = $time; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); end end end ]) begin ] == 'b1) && (Write_precharge[2] == 1'b1)) begin if ((($time - RAS_chk2 >= tRAS) && (((Burst_length_1 == ] >= ) || (Burst_length_2 == 'b1 && Count_precharge [2] >= 2) || (Burst_length_4 == 'b1 && Count_precharge [2] >= 4) || (Burst_length_8 == 'b1 && Count_precharge [2] >= 8))) || (RW_interrupt_write[] == 'b1 && WR_counter[2] >= 2)) begin Auto_precharge[] = 'b0; Write_precharge[] = 'b0; RW_interrupt_write[] = 'b0; #tWRa; // Wait for tWR Pc_b2 = 'b1; Act_b2 = 'b0; RP_chk2 = $time; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); end end end ]) begin ] == 'b1) && (Write_precharge[3] == 1'b1)) begin if ((($time - RAS_chk3 >= tRAS) && (((Burst_length_1 == ] >= ) || (Burst_length_2 == 'b1 && Count_precharge [3] >= 2) || (Burst_length_4 == 'b1 && Count_precharge [3] >= 4) || (Burst_length_8 == 'b1 && Count_precharge [3] >= 8))) || (RW_interrupt_write[] == 'b1 && WR_counter[3] >= 2)) begin Auto_precharge[] = 'b0; Write_precharge[] = 'b0; RW_interrupt_write[] = 'b0; #tWRa; // Wait for tWR Pc_b3 = 'b1; Act_b3 = 'b0; RP_chk3 = $time; if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); end end end task Burst; begin // Advance Burst Counter Burst_counter = Burst_counter + ; // Burst Type ] == 'b0) begin // Sequential Burst Col_temp = Col + ; ] == 'b1) begin // Interleaved Burst Col_temp[] = Burst_counter[] ^ Col_brst[]; Col_temp[] = Burst_counter[] ^ Col_brst[]; Col_temp[] = Burst_counter[] ^ Col_brst[]; end // Burst Length if (Burst_length_2) begin // Burst Length = 2 Col [] = Col_temp []; end else if (Burst_length_4) begin // Burst Length = 4 Col [ : ] = Col_temp [ : ]; end else if (Burst_length_8) begin // Burst Length = 8 Col [ : ] = Col_temp [ : ]; end else begin // Burst Length = FULL Col = Col_temp; end // Burst Read Single Write 'b1) begin Data_in_enable = 'b0; end // Data Counter 'b1) begin ) begin Data_in_enable = 'b0; Data_out_enable = 'b0; end 'b1) begin ) begin Data_in_enable = 'b0; Data_out_enable = 'b0; end 'b1) begin ) begin Data_in_enable = 'b0; Data_out_enable = 'b0; end 'b1) begin ) begin Data_in_enable = 'b0; Data_out_enable = 'b0; end end end endtask //**********************将SDRAM内的数据直接输出到外部文件*******************************// /* integer sdram_data,ind; always@(sdram_r) begin sdram_data=$fopen("sdram_data.txt"); $display("Sdram dampout begin ",sdram_data); // $fdisplay(sdram_data,"Bank0:"); for(ind=0;ind<=mem_sizes;ind=ind+1) $fdisplay(sdram_data,"%h %b",ind,Bank0[ind]); // $fdisplay(sdram_data,"Bank1:"); for(ind=0;ind<=mem_sizes;ind=ind+1) $fdisplay(sdram_data,"%h %b",ind,Bank1[ind]); // $fdisplay(sdram_data,"Bank2:"); for(ind=0;ind<=mem_sizes;ind=ind+1) $fdisplay(sdram_data,"%h %b",ind,Bank2[ind]); // $fdisplay(sdram_data,"Bank3:"); for(ind=0;ind<=mem_sizes;ind=ind+1) $fdisplay(sdram_data,"%h %b",ind,Bank3[ind]); $fclose("sdram_data.txt"); //->compare; end */ integer sdram_data,sdram_mem; :] aa,cc; :] bb,ee; always@(sdram_r) begin $display("Sdram dampout begin ",$realtime); sdram_data=$fopen("sdram_data.txt"); ;aa<*(mem_sizes+);aa=aa+) begin bb=aa[:]; if(aa<=mem_sizes) $fdisplay(sdram_data,"%0d %0h",aa,Bank0[bb]); *mem_sizes+) $fdisplay(sdram_data,"%0d %0h",aa,Bank1[bb]); *mem_sizes+) $fdisplay(sdram_data,"%0d %0h",aa,Bank2[bb]); else $fdisplay(sdram_data,"%0d %0h",aa,Bank3[bb]); end $fclose("sdram_data.txt"); sdram_mem=$fopen("sdram_mem.txt"); ;cc<*(mem_sizes+);cc=cc+) begin ee=cc[:]; if(cc<=mem_sizes) $fdisplay(sdram_mem,"%0h",Bank0[ee]); *mem_sizes+) $fdisplay(sdram_mem,"%0h",Bank1[ee]); *mem_sizes+) $fdisplay(sdram_mem,"%0h",Bank2[ee]); else $fdisplay(sdram_mem,"%0h",Bank3[ee]); end $fclose("sdram_mem.txt"); end // // Timing Parameters for -75 (PC133) and CAS Latency = 2 // specify // specparam //// tAH = 0.8, // Addr, Ba Hold Time //// tAS = 1.5, // Addr, Ba Setup Time //// tCH = 2.5, // Clock High-Level Width //// tCL = 2.5, // Clock Low-Level Width ////// tCK = 10.0, // Clock Cycle Time 100mhz ////// tCK = 7.5, // Clock Cycle Time 133mhz //// tCK = 7, // Clock Cycle Time 143mhz //// tDH = 0.8, // Data-in Hold Time //// tDS = 1.5, // Data-in Setup Time //// tCKH = 0.8, // CKE Hold Time //// tCKS = 1.5, // CKE Setup Time //// tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time //// tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time // tAH = 1, // Addr, Ba Hold Time // tAS = 1.5, // Addr, Ba Setup Time // tCH = 1, // Clock High-Level Width // tCL = 3, // Clock Low-Level Width //// tCK = 10.0, // Clock Cycle Time 100mhz //// tCK = 7.5, // Clock Cycle Time 133mhz // tCK = 7, // Clock Cycle Time 143mhz // tDH = 1, // Data-in Hold Time // tDS = 2, // Data-in Setup Time // tCKH = 1, // CKE Hold Time // tCKS = 2, // CKE Setup Time // tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time // tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time // $width (posedge Clk, tCH); // $width (negedge Clk, tCL); // $period (negedge Clk, tCK); // $period (posedge Clk, tCK); // $setuphold(posedge Clk, Cke, tCKS, tCKH); // $setuphold(posedge Clk, Cs_n, tCMS, tCMH); // $setuphold(posedge Clk, Cas_n, tCMS, tCMH); // $setuphold(posedge Clk, Ras_n, tCMS, tCMH); // $setuphold(posedge Clk, We_n, tCMS, tCMH); // $setuphold(posedge Clk, Addr, tAS, tAH); // $setuphold(posedge Clk, Ba, tAS, tAH); // $setuphold(posedge Clk, Dqm, tCMS, tCMH); // $setuphold(posedge Dq_chk, Dq, tDS, tDH); // endspecify endmodule
sdram_model_plus
7.最后附上仿真结果
打印信息,简单明了,这是我喜欢的风格
再来看看波形吧
完美,忙活了一天有些坑真的自己填,因为每填完一个坑,起身更强大,明天继续
2018/730
今天继续更新,有很多事耽搁了两天
二.仲裁机制和刷新操作
1.刷新操作是sdram必须的操作,使用不当数据指定丢失,具体为什么自己去查一下,我省的废话了。
既然是刷新,那么就应该有刷新的周期,这个怎么计算呢,打开datasheet,看图。红框意思是64ms内要进行8192次刷新,那么刷新周期大约7.8us
2.该刷新时序以及命令了
看下面的时序图等初始化完成后,刷新操作的第一步就是预充电(precharge),然后等tRP时间进行auto refresh(自刷新),后面再一次刷新和active都不用进行。前面哪个时间自己对应手册查一下,一般不会有错
这儿提一下,在预充电的时候,地址引脚要同时进行操作,A0~A9、A11、A12不用管,只对A10进行操作,如果A10位1,就是对所有bank进行充电,为0时选择bank进行充电,我们是为1。
3.刷新就说完了,该附上源代码了
module sdram_aref( //system signals input sclk , input s_rst_n , //comunicat with ARBIT input ref_en , output wire ref_req , output wire flag_ref_end , //others :] aref_cmd , :] sdram_addr , input flag_init_end ); //==============================================================================\ //*********************Define Parameter and Internal Signal ******************** //==============================================================================/ ; 'b0001 ; 'b0111 ; 'b0010 ; :] cmd_cnt ; :] ref_cnt ; reg flag_ref ; //=============================================================================\ //********************** Main Code *************************************** //=============================================================================/ always @(posedge sclk or negedge s_rst_n) begin 'b0) ref_cnt <= 'd0; else if(ref_cnt >= DELAY_78us) ref_cnt <= 'd0; 'b1) ref_cnt <= ref_cnt +'b1; end always @(posedge sclk or negedge s_rst_n) begin 'b0) flag_ref <= 'b0; 'b1) flag_ref <= 'b0; 'b1) flag_ref <= 'b1; end always @(posedge sclk or negedge s_rst_n ) begin 'b0) cmd_cnt <= 'd0; 'b1) cmd_cnt <= cmd_cnt + 'b1; else cmd_cnt <= 'd0; end always @(posedge sclk or negedge s_rst_n) begin 'b0) aref_cmd <= CMD_NOP; else case(cmd_cnt) : aref_cmd <= CMD_PRE; : aref_cmd <= CMD_AREF; default:aref_cmd <= CMD_NOP; endcase end 'b0; 'd0_0100_0000_0000; 'b1 : 1'b0; endmodule
sdram_aref
4.仲裁机制
为什么要这个仲裁机制,sdram工作是有刷新、写和读3个操作,我们需要这个仲裁机制来协调这三个操作,引用邓堪文老师一个图,大家一看就应该很明白了
5.具体的操作在sdram_top模块里,附上源码自己研究一下,这只写了三种状态,其他状态后面学习了在更新
module sdram_top( //system signals input sclk , input s_rst_n , //SDRAM Interfaces output wire sdram_clk , output wire sdram_cke , output wire sdram_cs_n , output wire sdram_cas_n , output wire sdram_ras_n , output wire sdram_we_n , :] sdram_bank , :] sdram_addr , :] sdram_dqm , :] sdram_dq ); //==============================================================================\ //*********************Define Parameter and Internal Signal ******************** //==============================================================================/ 'b0_0001 ; 'b0_0010 ; 'b0_0100 ; //init module wire flag_init_end ; :] init_cmd ; :] init_addr ; // :] state ; //refresh module wire ref_req ; wire flag_ref_end ; reg ref_en ; :] ref_cmd ; :] ref_addr ; //=============================================================================\ //********************** Main Code *************************************** //=============================================================================/ always @(posedge sclk or negedge s_rst_n) begin 'b0) state <= IDLE; else case(state) IDLE: 'b1) state <= ARBIT; else state <= IDLE; ARBIT: 'b1) state <= AREF; else state <= ARBIT; AREF: 'b1) state <= ARBIT; else state <=AREF; default: state <= IDLE; endcase end //ref_en always @(posedge sclk or negedge s_rst_n) begin 'b0) ref_en <= 'b0; 'b1) ref_en <= 'b1; else ref_en <= 'b0; end 'b1; assign sdram_addr = (state == IDLE) ? init_addr : ref_addr; assign {sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n} = (state == IDLE) ? init_cmd : ref_cmd; 'd0; assign sdram_clk = ~sclk; sdram_ini sdram_ini_inst( //systejm sign .sclk (sclk ), .s_rst_n (s_rst_n ), //others .cmd_reg (init_cmd ), .sdram_addr (init_addr ), .flag_init_end (flag_init_end ) ); sdram_aref sdram_aref_inst( //system signals .sclk (sclk ), .s_rst_n (s_rst_n ), //comunicat with ARBIT .ref_en (ref_en ), .ref_req (ref_req ), .flag_ref_end (flag_ref_end ), //others .aref_cmd (ref_cmd ), .sdram_addr (ref_addr ), .flag_init_end (flag_init_end ) ); endmodule
sdram_top
6.最后老规矩放上仿真结果以及仿真波形图
初始化没有错,刷星也一直进行,没有错误
在看看波形图,没次看到这些信号就觉得自己就是个大牛,哈哈哈! 自恋了,但是还是个入了门的菜鸡。看图信号和数据都没问题,完美!
2018.9.14
首先骂一下狗逼学校都要写完了停电了。我靠全没了,暑假就停了我那么久的网,还到处开挖,挖金子啊绝地三尺关键是堵道。无语了。。。
消气还是重写吧,一个多月了,打算每做好一个功能就更的,可惜就该这个狗逼学校事多还停水停网,但是我也没停下。现在补上吧,下午都快写完了突然停电主机关机了,呵呵,现在就这样了
首先看一下现在做好的图片显示系统,用串口发送640*480的图片给FPGA,波特率是1562500,最快的了,VGA驱动显示屏。
说实话我不想再从写了,很烦,还有很多事要忙,真心要学的可以私聊我!