added initial RTLs
This commit is contained in:
parent
23d946c51c
commit
38109d8297
|
|
@ -0,0 +1,109 @@
|
|||
// Background:
|
||||
// This DDR3 controller will be used with a DDR3-1600 with Kintex 7 FPGA Board (XC7K160T-3FFG676E).
|
||||
// The goal will be to:
|
||||
// - Run this at 1600Mbps (Maximum Physical Interface (PHY) Rate for a 4:1
|
||||
// memory controller based on "DC and AC Switching Characteristics" for Kintex 7)
|
||||
// - Parameterize everything
|
||||
// - Interface should be (nearly) bus agnostic
|
||||
// - High (sustained) data throughput. Sequential writes should be able to continue without interruption
|
||||
|
||||
`default_nettype none
|
||||
|
||||
`define DDR3_1600_11_11_11 // DDR3-1600 (11-11-11) speed bin
|
||||
|
||||
`define RAM_1Gb //DDR3 Capacity
|
||||
//`define RAM_2Gb
|
||||
//`define RAM_4Gb
|
||||
//`define RAM_8Gb
|
||||
|
||||
`define x8 //DDR3 organization (DQ bus width)
|
||||
//`define x4
|
||||
//`define x16
|
||||
|
||||
|
||||
module ddr3_controller #(
|
||||
parameter LANES = 8, //8 lanes of DQ
|
||||
parameter OPT_LOWPOWER = 1, //1 = low power, 0 = low logic
|
||||
parameter OPT_BUS_ABORT = 1 //1 = can abort bus, 0 = no abort (i_wb_cyc will be ignored, ideal for an AXI implementation which cannot abort transaction)(
|
||||
)
|
||||
(
|
||||
i_clk, i_rst_n,
|
||||
// Wishbone inputs
|
||||
i_wb_cyc,
|
||||
i_wb_stb,
|
||||
i_wb_we,
|
||||
i_wb_addr,
|
||||
i_wb_data,
|
||||
i_wb_sel,
|
||||
i_aux,
|
||||
// Wishbone outputs
|
||||
o_wb_ack,
|
||||
o_wb_stall,
|
||||
o_wb_data,
|
||||
o_aux
|
||||
// PHY Interface (to be added later)
|
||||
////////////////////////////////////
|
||||
);
|
||||
|
||||
`include "ddr3_parameters.vh"
|
||||
|
||||
input wire i_clk, i_rst_n; //200MHz input clock
|
||||
// Wishbone inputs
|
||||
input wire i_wb_cyc; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
|
||||
input wire i_wb_stb; //request a transfer
|
||||
input wire i_wb_we; //write-enable (1 = write, 0 = read)
|
||||
input wire[ADDR_BITS - 3 - 1:0] i_wb_addr; //{row, bank, col>>3}, this is WORD-ADRESSABLE (burst of 8 sequential address in 1 transaction)
|
||||
input wire[DQ_BITS*LANES*8 - 1:0] i_wb_data; //write data, 8 times the number of pins on the device (4:1 memory controller means 8 DDR transactions per controller clock)
|
||||
input wire[(DQ_BITS*LANES*8)/8 - 1:0] i_wb_sel; //byte strobe for write (1 = write the byte)
|
||||
input wire i_aux; //for AXI-interface compatibility (given upon strobe)
|
||||
// Wishbone outputs
|
||||
output reg o_wb_ack; //1 = read/write request has completed
|
||||
output reg o_wb_stall; //1 = busy, cannot accept requests
|
||||
output reg[DQ_BITS*LANES*8 - 1:0] o_wb_data; //read data, 8 times the number of pins on the device (4:1 memory controller means 8 DDR transactions per controller clock)
|
||||
output reg o_aux;//for AXI-interface compatibility (returned upon ack)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////// RESET and Initialization Procedure (JEDEC DDR3 doc pg. 19) ////////////////////////////////////////////////////////
|
||||
|
||||
//This reset and initialization process is designed for simplicity. This uses a Read-Only Memory (ROM))
|
||||
//to store the {ddr3ddr3_commands,time_delay(19:0)}. The output is registered to
|
||||
reg[31:0] reset_initialization_rom[15:0];
|
||||
|
||||
initial begin //{ { use-timer , stay-command , cke , reset_n } , CMD , TIMER or MRS}
|
||||
reset_initialization_rom[0] = {4'b1100 , CMD_NOP , ns_to_cycles(INITIAL_RESET_HIGH)};
|
||||
//1. RESET# needs to be maintained for minimum 200 us with stable power. CKE is pulled
|
||||
//“Low” anytime before RESET# being de-asserted (min. time 10 ns). .
|
||||
|
||||
reset_initialization_rom[1] = {4'b1101 , CMD_NOP, ns_to_cycles(INITIAL_CKE_LOW)};
|
||||
//2. After RESET# is de-asserted, wait for another 500 us until CKE becomes active. During this time, the
|
||||
//DRAM will start internal state initialization; this will be done independently of external clocks.
|
||||
// .... Also, a NOP or Deselect command must be registered (with tIS set up time to clock) before
|
||||
//CKE goes active.
|
||||
|
||||
reset_initialization_rom[2] = {4'b1111 , CMD_NOP, ns_to_cycles(TXPR)};
|
||||
//3. After CKE is being registered high, wait minimum of Reset CKE Exit time, tXPR.
|
||||
|
||||
reset_initialization_rom[3] = {4'b0011, CMD_MRS, MR2[18:0]};
|
||||
//4. Delay of TMRD between MRS commands is 4nCK (DDR3 clock cycle). In a 4:1 controller, this is just a 1 clock cycle delay thus no delay is actually needed.
|
||||
|
||||
|
||||
end
|
||||
|
||||
//notes:
|
||||
//ODT must be statically held low at all times (except for write of course) when RTT_NOM is enabled via MR1.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//convert nanoseconds time input to number of clock cycles (referenced to CONTROLLER_CLK_PERIOD)
|
||||
function [18:0] ns_to_cycles (input[19:0] ns);
|
||||
ns_to_cycles = $ceil(ns/CONTROLLER_CLK_PERIOD);
|
||||
endfunction
|
||||
|
||||
|
||||
`ifdef FORMAL
|
||||
|
||||
end
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
// Some parameters are salvaged from Micron DDR3 Simulation Model Files ( https://www.micron.com/products/dram/ddr3-sdram/part-catalog/mt41k128m16jt-125 )
|
||||
|
||||
|
||||
localparam CONTROLLER_CLK_PERIOD = 5.0; //200MHz controller clock (5ns)
|
||||
localparam DDR3_CLK_PERIOD = 1.25; //800MHz DDR3 clock (1.25ns)
|
||||
|
||||
////////////////////////////////////////////////////////////// COMMAND PARAMETERS //////////////////////////////////////////////////////////////
|
||||
|
||||
//DDR3 commands {cs_n, ras_n, cas_n, we_n} (JEDEC DDR3 doc pg. 33 )
|
||||
localparam[3:0] CMD_MRS = 4'b0000; // Mode Register Set
|
||||
localparam[3:0] CMD_REF = 4'b0001; // Refresh
|
||||
localparam[3:0] CMD_PRE = 4'b0010; // Precharge (A10-AP: 0 = Single Bank Precharge, 1 = Precharge All Banks)
|
||||
localparam[3:0] CMD_ACT = 4'b0011; // Bank Activate
|
||||
localparam[3:0] CMD_WR = 4'b0100; // Write (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
|
||||
localparam[3:0] CMD_RD = 4'b0101; //Read (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
|
||||
localparam[3:0] CMD_NOP = 4'b0111; // No Operation
|
||||
localparam[3:0] CMD_DES = 4'b1000; // Deselect command performs the same function as No Operation command (JEDEC DDR3 doc pg. 34 NOTE 11)
|
||||
localparam[3:0] CMD_ZQC = 4'b0110; // ZQ Calibration (A10-AP: 0 = ZQ Calibration Short, 1 = ZQ Calibration Long)
|
||||
|
||||
localparam RST_USE_TIMER = 26; // Command bit that determines if timer will be used
|
||||
localparam RST_STAY_COMMAND = 25; //Command bit that determines if command will last for entire timer duration (or if
|
||||
localparam RST_CKE = 24; //Control clock-enable input to DDR3
|
||||
localparam RST_RESET_N = 23; //Control reset to DDR3
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////// SET MODE REGISTERS //////////////////////////////////////////////////////////////
|
||||
|
||||
localparam[2:0] PASR = 3'b000; //Partial Array Self-Refresh: Full Array
|
||||
localparam[2:0] CWL = 3'b011; //CAS write Latency: 8 (1.5 ns > tCK(avg) >= 1.25 ns)
|
||||
localparam ASR = 1'b1; //Auto Self-Refresh: on
|
||||
localparam SRT = 1'b0; //Self-Refresh Temperature Range:0 (If ASR = 1, SRT bit must be set to 0)
|
||||
localparam[1:0] RTT_WR = 2'b00; //Dynamic ODT: off
|
||||
localparam[18:0] MR2 = {3'b010, 5'b00000, RTT_WR, 1'b0, SRT, ASR, CWL, PASR};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
localparam INITIAL_RESET_HIGH = 200_000; // 200us reset must be high at initialization
|
||||
localparam INITIAL_CKE_LOW = 500_000; // 500us cke must be low before activating
|
||||
|
||||
`ifdef DDR3_1600_11_11_11 //DDR3-1600 (11-11-11) speed bin
|
||||
localparam TRAS = 35; // tRAS ns Minimum Active to Precharge command time
|
||||
localparam TRC = 48.750; // tRC ns Active to Active/Auto Refresh command time
|
||||
localparam TRCD = 13.750; // tRCD ns Active to Read/Write command time
|
||||
localparam TRP = 13.750; // tRP ns Precharge command period
|
||||
`endif
|
||||
|
||||
`ifdef RAM_1Gb
|
||||
localparam TRFC = 110; // ns Refresh command to ACT or REF
|
||||
`elsif RAM_2Gb
|
||||
localparam TRFC = 160; // ns Refresh command to ACT or REF
|
||||
`elsif RAM_4Gb
|
||||
localparam TRFC = 300; // ns Refresh command to ACT or REF
|
||||
`else
|
||||
localparam TRFC = 350; // ns Refresh command to ACT or REF
|
||||
`endif
|
||||
|
||||
localparam TXPR = max(5*DDR3_CLK_PERIOD,TRFC+10); // tXPR ns Exit Reset from CKE HIGH to a valid command
|
||||
localparam TMRD = 4; // tMRD nCK Mode Register Set command cycle time
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////// I/O Interface Width //////////////////////////////////////////////////////////////
|
||||
|
||||
`ifdef RAM_1Gb
|
||||
`ifdef x4
|
||||
localparam DM_BITS = 1; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 14 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 14; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 11; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 4 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`elsif x8
|
||||
localparam DM_BITS = 1; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 14 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 14; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 8 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1; // Set this localparam to control how many Dqs bits are used
|
||||
`else
|
||||
localparam DM_BITS = 2; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 13 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 13 ; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10 ; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 16; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 2; // Set this localparam to control how many Dqs bits are used
|
||||
`endif
|
||||
|
||||
`elsif RAM_2Gb
|
||||
`ifdef x4
|
||||
localparam DM_BITS = 1 ; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 15 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 15; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 11; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 4 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`elsif x8
|
||||
localparam DM_BITS = 1 // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 15 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 15; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10 ; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 8; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`else
|
||||
localparam x16
|
||||
localparam DM_BITS = 2 ; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 14 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 14 ; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10 ; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 16 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 2 ; // Set this localparam to control how many Dqs bits are used
|
||||
`endif
|
||||
|
||||
`elsif RAM_4Gb
|
||||
`ifdef x4
|
||||
localparam DM_BITS = 1; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 16 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 16; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 11; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 4; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`elsif x8
|
||||
localparam DM_BITS = 1; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 16 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 16 ; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 8 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`else
|
||||
localparam x16
|
||||
localparam DM_BITS = 2; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 15 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 15; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10 ; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 16; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 2 ; // Set this localparam to control how many Dqs bits are used
|
||||
`endif
|
||||
|
||||
`else
|
||||
`ifdef x4
|
||||
localparam DM_BITS = 1 ; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 16 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 16; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 14; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 4 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`elsif x8
|
||||
localparam DM_BITS = 1 ; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 16 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 16 ; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 11; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 8 ; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 1 ; // Set this localparam to control how many Dqs bits are used
|
||||
`else
|
||||
localparam DM_BITS = 2; // Set this localparam to control how many Data Mask bits are used
|
||||
localparam ADDR_BITS = 16 ; // MAX Address Bits
|
||||
localparam ROW_BITS = 16; // Set this localparam to control how many Address bits are used
|
||||
localparam COL_BITS = 10; // Set this localparam to control how many Column bits are used
|
||||
localparam DQ_BITS = 16; // Set this localparam to control how many Data bits are used **Same as part bit width**
|
||||
localparam DQS_BITS = 2 ; // Set this localparam to control how many Dqs bits are used
|
||||
`endif
|
||||
`endif
|
||||
|
||||
localparam BA_BITS = 3 ; // Set this parmaeter to control how many Bank Address bits are used
|
||||
localparam AP = 10 ; // the address bit that controls auto-precharge and precharge-all
|
||||
localparam BC = 12; // the address bit that controls burst chop
|
||||
|
||||
|
||||
|
||||
function integer max(input integer a, input integer b);
|
||||
if(a >= b) max = a;
|
||||
else max = b;
|
||||
endfunction
|
||||
|
||||
Loading…
Reference in New Issue