📄 sdram_cnt.v
字号:
`include "sdram_defines.v"
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
//*******************************************************************************
// S Y N T H E S I Z A B L E S D R A M C O N T R O L L E R C O R E
//
// This core adheres to the GNU Public License
//
// This is a synthesizable Synchronous DRAM controller Core. As it stands,
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B.
//
// The core has been carefully coded so as to be "platform-independent".
// It has been successfully compiled and simulated under three separate
// FPGA/CPLD platforms:
// Xilinx Foundation Base Express V2.1i
// Altera Max+PlusII V9.21
// Lattice ispExpert V7.0
//
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous
// and supports ony one transfer at a time. That is, burst-mode transfers
// are not yet supported. In may ways, the interface to this core is much
// like that of a typical SRAM. The hand-shaking between the host and the
// SDRAM core is done through the "sdram_busy_l" signal generated by the
// core. Whenever this signal is active low, the host must hold the address,
// data (if doing a write), size and the controls (cs, rd/wr).
//
// Connection Diagram:
// SDRAM side:
// sd_wr_l connect to -WR pin of SDRAM
// sd_cs_l connect to -CS pin of SDRAM
// sd_ras_l connect to -RAS pin of SDRAM
// sd_cas_l connect to -CAS pin of SDRAM
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins
// sd_addx[10:0] connect to the Address bus [10:0]
// sd_data[31:0] connect to the data bus [31:0]
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM
//
// HOST side:
// mp_addx[22:0] connect to the address bus of the host.
// 23 bit address bus give access to 8Mbyte
// of the SDRAM, as byte, half-word (16bit)
// or word (32bit)
// mp_data_in[31:0] Unidirectional bus connected to the data out
// of the host. To use this, enable
// "databus_is_unidirectional" in INC.H
// mp_data_out[31:0] Unidirectional bus connected to the data in
// of the host. To use this, enable
// "databus_is_unidirectional" in INC.H
// mp_data[31:0] Bi-directional bus connected to the host's
// data bus. To use the bi-directionla bus,
// disable "databus_is_unidirectional" in INC.H
// mp_rd_l Connect to the -RD output of the host
// mp_wr_l Connect to the -WR output of the host
// mp_cs_l Connect to the -CS of the host
// mp_size[1:0] Connect to the size output of the host
// if there is one. When set to 0
// all trasnfers are 32 bits, when set to 1
// all transfers are 8 bits, and when set to
// 2 all xfers are 16 bits. If you want the
// data to be lower order aligned, turn on
// "align_data_bus" option in INC.H
// sdram_busy_l Connect this to the wait or hold equivalent
// input of the host. The host, must hold the
// bus if it samples this signal as low.
// sdram_mode_set_l When a write occurs with this set low,
// the SDRAM's mode set register will be programmed
// with the data supplied on the data_bus[10:0].
//
//
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com
//
//*******************************************************************************
//
// Hierarchy:
//
// SDRAM.V Top Level Module
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from
// is with the HOSTCONT.
// optional
// MICRO.V This is the built in SDRAM tester. This module generates
// a number of test logics which is used to test the SDRAM
// It is basically a Micro bus generator.
//
/*
*/
module sdram_cnt(
// system level stuff
sys_rst_l,
sys_clk,
// SDRAM connections
sd_cs_l,
sd_ras_l,
sd_cas_l,
sd_dqm,
// Host Controller connections
do_mode_set,
do_read,
do_write,
doing_refresh,
sd_addx_mux,
sd_addx10_mux,
sd_rd_ena,
sd_data_ena,
modereg_cas_latency,
modereg_burst_length,
mp_data_mux,
decoded_dqm,
do_write_ack,
do_read_ack,
do_modeset_ack,
pwrup,
go,
busy,
refresh_timer_val,
ras2cas_delay_val,
refresh2anything_delay_val,
row_active_time_val,
last_data_in_to_row_precharge_val,
precharge_to_ras_val,
do_refresh,
load_address,
load_data,
load_dqm,
assert_we,
// debug
next_state,
autorefresh_cntr,
autorefresh_cntr_l,
cntr_limit
);
parameter state_idle = 'b0000000000000001 ;
parameter state_set_ras = 'b0000000000000010 ;
parameter state_ras_dly = 'b0000000000000100 ;
parameter state_set_cas = 'b0000000000001000 ;
parameter state_cas_latency1 = 'b0000000000010000 ;
parameter state_cas_latency2 = 'b0000000000100000 ;
parameter state_write = 'b0000000001000000 ;
parameter state_read = 'b0000000010000000 ;
parameter state_auto_refresh = 'b0000000100000000 ;
parameter state_auto_refresh_dly = 'b0000001000000000 ;
parameter state_precharge = 'b0000010000000000 ;
parameter state_powerup = 'b0000100000000000 ;
parameter state_modeset = 'b0001000000000000 ;
parameter state_delay_Trp = 'b0010000000000000 ;
parameter state_delay_Tras1 = 'b0100000000000000 ;
parameter state_delay_Tras2 = 'b1000000000000000 ;
// Refresh timer states
parameter state_count = 'b0 ;
parameter state_halt = 'b1 ;
// ****************************************
//
// I/O DEFINITION
//
// ****************************************
// System level stuff
input sys_rst_l;
input sys_clk;
// SDRAM connections
output sd_cs_l;
output sd_ras_l;
output sd_cas_l;
output [3:0] sd_dqm;
// Host Controller connections
input do_mode_set;
input do_read;
input do_write;
output doing_refresh;
output [1:0] sd_addx_mux;
output [1:0] sd_addx10_mux;
output sd_rd_ena;
output sd_data_ena;
input [2:0] modereg_cas_latency;
input [2:0] modereg_burst_length;
output mp_data_mux;
input [3:0] decoded_dqm;
output do_write_ack;
output do_read_ack;
output do_modeset_ack;
output pwrup;
input go ;
output busy ;
reg busy ;
input [15:0] refresh_timer_val ;
input [1:0] ras2cas_delay_val ;
input [3:0] refresh2anything_delay_val ;
input [3:0] row_active_time_val ;
input [1:0] last_data_in_to_row_precharge_val ;
input [1:0] precharge_to_ras_val ;
output do_refresh ;
output load_address,
load_data,
load_dqm,
assert_we ;
reg load_address,
load_data,
load_dqm,
assert_we ;
assign sd_data_ena = load_data ;
// Debug
output [15:0] next_state;
output [3:0] autorefresh_cntr;
output autorefresh_cntr_l;
output [12:0] cntr_limit;
// ****************************************
//
// Memory Elements
//
// ****************************************
//
reg [15:0] next_state;
reg [15:0] refresh_timer;
reg sd_cs_l;
reg sd_ras_l;
reg sd_cas_l;
reg [3:0] sd_dqm;
reg [1:0] sd_addx_mux;
reg [1:0] sd_addx10_mux;
reg pwrup; // this variable holds the power up condition
reg [12:0] refresh_cntr; // this is the refresh counter
reg refresh_cntr_l; // this is the refresh counter reset signal
reg [3:0] burst_length_cntr;
reg burst_cntr_ena;
reg sd_rd_ena; // read latch gate, active high
reg [12:0] cntr_limit;
reg [3:0] modereg_burst_count;
reg refresh_state;
reg mp_data_mux;
reg do_refresh; // this bit indicates autorefresh is due
reg doing_refresh; // this bit indicates that the state machine is
// doing refresh.
reg [3:0] autorefresh_cntr;
reg autorefresh_cntr_l;
reg do_write_ack;
reg do_read_ack;
reg do_modeset_ack;
reg do_refresh_ack;
reg [1:0] ras2cas_delay_count ;
reg ras2cas_delay_count_enable ;
reg [3:0] row_active_time_count ;
reg row_active_time_count_enable ;
reg [1:0] last_data_in_to_row_precharge_count ;
reg last_data_in_to_row_precharge_count_enable ;
reg [1:0] precharge_to_ras_count ;
reg precharge_to_ras_count_enable ;
always@(posedge sys_clk or negedge sys_rst_l)
begin
if (~sys_rst_l)
precharge_to_ras_count <= #1 2'h0 ;
else if ( !precharge_to_ras_count_enable )
precharge_to_ras_count <= #1 precharge_to_ras_val ;
else if (precharge_to_ras_count != 1)
precharge_to_ras_count <= #1 precharge_to_ras_count - 1'b1 ;
end
wire precharge_time_expired = (precharge_to_ras_count == 2) || (precharge_to_ras_count == 1) ;
always@(posedge sys_clk or negedge sys_rst_l)
begin
if (~sys_rst_l)
last_data_in_to_row_precharge_count <= #1 0 ;
else if ( !last_data_in_to_row_precharge_count_enable )
last_data_in_to_row_precharge_count <= #1 last_data_in_to_row_precharge_val ;
else if ( last_data_in_to_row_precharge_count != 1 )
last_data_in_to_row_precharge_count <= #1 last_data_in_to_row_precharge_count - 1'b1 ;
end
always@(posedge sys_clk or negedge sys_rst_l)
begin
if (~sys_rst_l)
row_active_time_count <= #1 4'hF ;
else if ( !row_active_time_count_enable )
row_active_time_count <= #1 row_active_time_val ;
else if ( row_active_time_count != 4'h1 )
row_active_time_count <= #1 row_active_time_count - 1'b1 ;
end
//wire row_can_be_precharged = (row_active_time_count == 4'h0) || (row_active_time_count == 4'h1) || (row_active_time_count == 4'h2);
wire row_can_be_precharged = ((row_active_time_count == 2) || (row_active_time_count == 1)) ;
always@(posedge sys_clk or negedge sys_rst_l)
begin
if (~sys_rst_l)
ras2cas_delay_count <= #1 2 ;
else if (!ras2cas_delay_count_enable)
ras2cas_delay_count <= #1 2 ;
else
ras2cas_delay_count <= #1 ras2cas_delay_count + 1'b1 ;
end
// State Machine
always @(posedge sys_clk or negedge sys_rst_l)
if (~sys_rst_l) begin
next_state <=state_powerup;
autorefresh_cntr_l <= #1 1'b0;
refresh_cntr_l <= #1 1'b0;
pwrup <= #1 1'b1 ; // high indicates we've just power'd up or RESET
sd_cs_l <= #1 1'b1 ;
sd_ras_l <= #1 1'b1 ;
sd_cas_l <= #1 1'b1 ;
sd_dqm <= #1 4'hF;
sd_addx_mux <= #1 2'b10; // select the mode reg default value
sd_addx10_mux <= #1 2'b11; // select 1 as default
sd_rd_ena <= #1 1'b0;
mp_data_mux <= #1 1'b0;
// refresh_cntr<= 13'h0000;
burst_cntr_ena <= #1 1'b0; // do not enable the burst counter
doing_refresh <= #1 1'b0;
do_write_ack <= #1 1'b0; // do not ack as reset default
do_read_ack <= #1 1'b0; // do not ack as reset default
do_modeset_ack <= #1 1'b0; // do not ack as reset default
do_refresh_ack <= #1 1'b0;
busy <= #1 1'b1 ;
ras2cas_delay_count_enable <= #1 1'b0 ;
row_active_time_count_enable <= #1 1'b0 ;
last_data_in_to_row_precharge_count_enable <= #1 1'b0 ;
precharge_to_ras_count_enable <= #1 1'b0 ;
load_address <= #1 1'b0 ;
load_data <= #1 1'b0 ;
load_dqm <= #1 1'b0 ;
assert_we <= #1 1'b0 ;
end
else case (next_state)
// Power Up state
state_powerup: begin
next_state <= #1 state_precharge;
sd_addx10_mux <= #1 2'b11; // A10 = 1'b1
load_address <= #1 1'b1 ;
assert_we <= #1 1'b1 ;
precharge_to_ras_count_enable <= #1 1'b1 ;
sd_cs_l <= #1 1'b1;
sd_ras_l <= #1 1'b1;
sd_cas_l <= #1 1'b1;
sd_dqm <= #1 4'hF;
sd_rd_ena <= #1 1'b0;
pwrup <= #1 1'b1; // this is the power up run
burst_cntr_ena <= #1 1'b0; // do not enable the burst counter
refresh_cntr_l <= #1 1'b1; // allow the refresh cycle counter to count
end
// PRECHARGE both (or all) banks
state_precharge: begin
assert_we <= #1 1'b0;
sd_cs_l <= #1 1'b0;
sd_ras_l <= #1 1'b0;
sd_cas_l <= #1 1'b1;
sd_dqm <= #1 4'hF;
load_address <= #1 1'b0 ;
load_dqm <= #1 1'b0 ;
if (precharge_time_expired)
begin
next_state <= #1 state_idle;
precharge_to_ras_count_enable <= #1 1'b0 ;
end
else
begin
next_state <= #1 state_delay_Trp;
end
end
// Delay Trp
// this delay is needed to meet the minimum precharge to new command
// delay. For most parts, this is 20nS, which means you need 1 clock cycle
// of NOP at 100MHz
state_delay_Trp: begin
sd_cs_l <= #1 1'b1;
sd_ras_l <= #1 1'b1;
if (precharge_time_expired)
begin
next_state <= #1 state_idle ;
precharge_to_ras_count_enable <= #1 1'b0 ;
end
end
// Autorefresh
state_auto_refresh: begin
sd_cs_l <= #1 1'b0;
sd_ras_l <= #1 1'b0;
sd_cas_l <= #1 1'b0;
next_state <= #1 state_auto_refresh_dly;
autorefresh_cntr_l <= #1 1'b1; //allow refresh delay cntr (Trc) to tick
do_refresh_ack <= #1 1'b1; // acknowledge refresh request
end
// This state generates the Trc delay.
// this delay is the delay from the refresh command to the next valid command
// most parts require this to be 60 to 70nS. So at 100MHz, we need at least
// 6 NOPs.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -