URL
https://opencores.org/ocsvn/sdram/sdram/trunk
Subversion Repositories sdram
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/inc.h
0,0 → 1,89
// Uncomment below to use the microprocessor bus simulator |
// ==================== |
`define simulate_mp |
|
// Uncomment the below to enable the debug pins |
// ==================== |
//`define show_debug |
|
|
// Common definition stuff |
`define HI 1'b1 |
`define LO 1'b0 |
`define X 1'bx |
|
//*********************************************************** |
// U S E R M O D I F I A B L E S |
//*********************************************************** |
|
// The number of refreshses done at power up. 16 by default |
`define power_up_ref_cntr_limit 16 |
|
// The number of refreshes done during normal refresh cycle. |
// Set this to be 2048 for "burst" refreshes, and |
// set this to be 1 for "regular" refreshes |
`define auto_ref_cntr_limit 1 |
|
// Refresh Frequency in Hz. |
// For burst refresh use 33Hz (30mS) |
// For normal refresh use 66666Hz (15uS) |
`define Frefresh 85000 |
|
// SDRAM clock frequency in Hz. |
// Set this to whatever the clock rate is |
//`define Fsystem 12500000 |
`define Fsystem 6250000 |
|
|
// Clock divider |
// Only choose one of these |
//`define divide_by_2 |
`define divide_by_4 |
//`define divide_by_8 |
|
//*********************************************************** |
// D O N O T M O D I F Y |
//*********************************************************** |
// Interval between refreshes in SDRAM clk ticks |
`define RC `Fsystem/`Frefresh |
|
// Width of the refresh counter. Default 20. log2(`RC)/log2 |
// use 8 bits for 15uS interval with 12.5MHz clock |
`define BW 8 |
//`define BW 20 |
|
// The refresh delay counter width |
`define RD 3 |
|
// This sets the number of delay cycles right after the refresh command |
`define AUTO_REFRESH_WIDTH 1 |
|
// MAin SDRAM controller state machine definition |
`define TS 4 |
`define TSn `TS-1 |
|
`define state_idle `TS'b0001 |
`define state_set_ras `TS'b0011 |
`define state_ras_dly `TS'b0010 |
`define state_set_cas `TS'b0110 |
`define state_cas_latency1 `TS'b0111 |
`define state_cas_latency2 `TS'b0101 |
`define state_write `TS'b0100 |
`define state_read `TS'b1100 |
`define state_auto_refresh `TS'b1101 |
`define state_auto_refresh_dly `TS'b1111 |
`define state_precharge `TS'b1110 |
`define state_powerup `TS'b1010 |
`define state_modeset `TS'b1011 |
`define state_cool_off `TS'b1001 |
`define state_x1 `TS'b0000 |
`define state_x2 `TS'b1000 |
//`define state_x3 `TS'h10 |
//`define state_x4 `TS'h11 |
|
|
// Fresh timer states |
`define state_count 3'b001 |
`define state_halt 3'b010 |
`define state_reset 3'b100 |
|
/trunk/sdramcnt.v
0,0 → 1,451
`include "inc.h" |
|
// |
// SDRAMCNT.v |
// |
// SDRAM controller. |
// This module can control Synchronous DRAMS such as |
// Samsumg's KM416S1020/KM416S1120 1MB X 16 |
// NEC's uPD451616 1MB X 16 |
// Oki's MSM56V16160 |
// |
// The SDRAM's internal MODE REGISTER is also programmable. |
// |
// |
|
|
module sdramcnt( |
// system level stuff |
sys_rst_l, |
sys_clk, |
|
// SDRAM connections |
sd_clke, |
sd_wr_l, |
sd_cs_l, |
sd_ras_l, |
sd_cas_l, |
sd_ldqm, |
sd_udqm, |
|
// 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, |
|
// debug |
next_state, |
autorefresh_cntr, |
autorefresh_cntr_l, |
pwrup, |
cntr_limit |
|
); |
|
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
|
|
// System level stuff |
input sys_rst_l; |
input sys_clk; |
|
// SDRAM connections |
output sd_wr_l; |
output sd_cs_l; |
output sd_ras_l; |
output sd_cas_l; |
output sd_ldqm; |
output sd_udqm; |
output sd_clke; |
|
// 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; |
|
// Debug |
output [3:0] next_state; |
output [12:0] autorefresh_cntr; |
output autorefresh_cntr_l; |
output pwrup; |
output [12:0] cntr_limit; |
|
// **************************************** |
// |
// Memory Elements |
// |
// **************************************** |
// |
reg [3:0] next_state; |
reg [7:0] refresh_timer; |
reg sd_wr_l; |
reg sd_cs_l; |
reg sd_ras_l; |
reg sd_cas_l; |
reg sd_ldqm; |
reg sd_udqm; |
reg [1:0] sd_addx_mux; |
reg [1:0] sd_addx10_mux; |
reg sd_data_ena; |
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 [2:0] refresh_state; |
reg mp_data_mux; |
wire do_refresh; // this bit indicates autorefresh is due |
reg doing_refresh; // this bit indicates that the state machine is |
// doing refresh. |
reg [12:0] autorefresh_cntr; |
reg autorefresh_cntr_l; |
|
assign sd_clke = `HI; // clk always enabled |
|
// State Machine |
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
next_state <= `state_powerup; |
autorefresh_cntr_l <= `LO; |
refresh_cntr_l <= `LO; |
pwrup <= `HI; |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_data_ena <= `LO; |
sd_addx_mux <= 2'b10; // select the mode reg default value |
sd_addx10_mux <= 2'b11; // select 1 as default |
sd_rd_ena <= `LO; |
mp_data_mux <= `LO; |
// refresh_cntr<= 13'h0000; |
burst_cntr_ena <= `LO; // do not enable the burst counter |
doing_refresh <= `LO; |
end |
else case (next_state) |
// Power Up state |
`state_powerup: begin |
next_state <= `state_precharge; |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_data_ena <= `LO; |
sd_addx_mux <= 2'b10; |
sd_rd_ena <= `LO; |
pwrup <= `HI; // this is the power up run |
burst_cntr_ena <= `LO; // do not enable the burst counter |
refresh_cntr_l <= `HI; // allow the refresh cycle counter to count |
end |
|
// PRECHARGE both banks |
`state_precharge: begin |
// refresh_cntr<= refresh_cntr + 1; // one less ref cycle to do |
sd_wr_l <= `LO; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_addx10_mux <= 2'b11; // A10 = 1'b1 |
if ( (refresh_cntr == cntr_limit) & (pwrup == `HI) ) begin |
doing_refresh <= `LO; // refresh cycle is done |
// refresh_cntr <= 13'h000; // ..reset refresh counter |
refresh_cntr_l <= `LO; // ..reset refresh counter |
next_state <= `state_modeset; // if this was power-up, then go and set mode reg |
pwrup <= `LO; // ..no more in power up mode |
end else begin |
doing_refresh <= `HI; // indicate that we're doing refresh |
next_state <= `state_auto_refresh; |
end |
end |
|
// Autorefresh |
`state_auto_refresh: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `LO; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_addx10_mux <= 2'b01; // A10 = 0 |
next_state <= `state_auto_refresh_dly; |
autorefresh_cntr_l <= `HI; //allow delay cntr to tick |
end |
|
// Autor Refresh Delay -- extends the AutoRefresh CMD by |
// AUTO_REFRESH_WIDTH counts |
`state_auto_refresh_dly: begin |
if (autorefresh_cntr == `AUTO_REFRESH_WIDTH) begin |
autorefresh_cntr_l <= `LO; |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
// If all refresh is done |
if ((refresh_cntr == cntr_limit) & (pwrup == `LO)) begin |
doing_refresh <= `LO; // refresh cycle is done |
// refresh_cntr <= 13'h000; // ..reset refresh counter |
refresh_cntr_l <= `LO; // ..reset refresh counter |
if (do_write | do_read) |
next_state <= `state_set_ras; // go service a pending read or write if any |
else |
next_state <= `state_idle; // if there are no peding RD or WR, then go to idle state |
end |
// IF refresh cycles not done yet.. |
else |
next_state <= `state_precharge; |
end |
end |
|
// MODE SET state |
`state_modeset: begin |
next_state <= `state_idle; |
sd_wr_l <= `LO; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `LO; |
if (~pwrup) begin // select a10-a0 to be the data from mode set reg |
sd_addx_mux <= 2'b10; |
sd_addx10_mux <= 2'b10; |
end |
end |
|
// IDLE state |
`state_idle: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_data_ena <= `LO; // turn off the data bus drivers |
sd_addx10_mux <= 2'b01; // select low |
mp_data_mux <= `LO; // drive the SD data bus with normal data |
if (do_write | do_read ) |
next_state <= `state_set_ras; |
else if (do_mode_set) |
next_state <= `state_modeset; |
else if (do_refresh) begin |
next_state <= `state_precharge; |
refresh_cntr_l <= `HI; // allow refresh cycle counter to count up |
end |
end |
|
// SET RAS state |
`state_set_ras: begin |
sd_cs_l <= `LO; // enable SDRAM |
sd_ras_l <= `LO; // enable the RAS |
sd_addx_mux <= 2'b00; // send the low 10 bits of mp_addx to SDRAM |
next_state <= `state_ras_dly; // wait for a bit |
end |
|
// RAS delay state. This state may not be necessary for most |
// cases. Fow now, it is here to kill 1-cycle time |
`state_ras_dly: begin |
sd_cs_l <= `HI; // disable SDRAM |
sd_ras_l <= `HI; // disble the RAS |
if (do_write) |
next_state <= `state_write; // if write, do the write |
else |
next_state <= `state_set_cas; // if read, do the read |
end |
|
// WRITE state |
`state_write: begin |
sd_cs_l <= `LO; // enable SDRAM |
sd_cas_l <= `LO; // enable the CAS |
sd_addx_mux <= 2'b01; // send the lower 8 bits of mp_addx to SDRAM (CAS addx) |
// remember that the mp_addr[19] is the sd_ba |
sd_addx10_mux <= 2'b00; // set A10/AP = mp_addx[18] |
sd_data_ena <= `HI; // turn on the data bus drivers |
sd_wr_l <= `LO; // enable the write |
sd_ldqm <= `LO; // do not mask |
sd_udqm <= `LO; // do not mask |
next_state <= `state_cool_off; |
end |
|
// SET CAS state |
`state_set_cas: begin |
sd_cs_l <= `LO; |
sd_cas_l <= `LO; |
sd_addx_mux <= 2'b01; |
sd_addx10_mux <= 2'b00; |
sd_ldqm <= `LO; // do not mask |
sd_udqm <= `LO; // do not mask |
next_state <= `state_cas_latency1; |
end |
|
`state_cas_latency1: begin |
sd_cs_l <= `HI; // disable CS |
sd_cas_l <= `HI; // disable CAS |
if (modereg_cas_latency==3'b010) begin |
next_state <= `state_read; // 2 cycles of lantency done. |
burst_cntr_ena <= `HI; // enable he burst lenght counter |
end else |
next_state <= `state_cas_latency2; // 3 cycles of latency |
end |
|
`state_cas_latency2: begin |
next_state <= `state_read; |
burst_cntr_ena <= `HI; // enable the burst lenght counter |
end |
|
`state_read: begin |
if (burst_length_cntr == modereg_burst_count) begin |
burst_cntr_ena <= `LO; // done counting; |
sd_rd_ena <= `LO; // done with the reading |
next_state <= `state_cool_off; |
end else |
sd_rd_ena <= `HI; // enable the read latch on the next state |
end |
|
`state_cool_off: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_ldqm <= `HI; |
sd_udqm <= `HI; |
sd_addx10_mux <= 2'b01; // select the mp_addx[10] |
mp_data_mux <= `HI; // drive the SD data bus with all zeros |
next_state <= `state_idle; |
end |
|
endcase |
|
|
// This counter is used to extend the width of the Auto Refresh |
// command. It was found that if the AutoRefresh CMD set to be the default of |
// 1 SDRAM_CLK cycle, then an AutoRefresh CMD in the middle of a burst read |
// would mess-up the remining burst reads. By extending the Auto Refresh cycle |
// to 2 or more, this burst read problem was solved. As to why this happens |
// I did not investigate further. |
always @(posedge sys_clk or negedge autorefresh_cntr_l) |
if (~autorefresh_cntr_l) |
autorefresh_cntr <= 13'h0000; |
else |
autorefresh_cntr <= autorefresh_cntr + 1; |
|
|
|
// This mux selects the cycle limit value for the |
// auto refresh counter |
always @(pwrup) |
case (pwrup) |
/* `HI: cntr_limit <= `power_up_ref_cntr_limit; |
default: cntr_limit <= `auto_ref_cntr_limit; |
*/ |
1'b1: cntr_limit <= 13'h000F; |
default: cntr_limit <= 13'h0001; |
endcase |
|
|
// |
// BURST LENGHT COUNTER |
// |
// This is the burst length counter. |
always @(posedge sys_clk or negedge burst_cntr_ena) |
if (~burst_cntr_ena) |
burst_length_cntr <= 3'b000; // reset whenever 'burst_cntr_ena' is low |
else |
burst_length_cntr <= burst_length_cntr + 1; |
|
// |
// REFRESH_CNTR |
// |
always @(posedge sys_clk or negedge refresh_cntr_l) |
if (~refresh_cntr_l) |
refresh_cntr <= 13'h0000; |
else if (next_state == `state_auto_refresh) |
refresh_cntr <= refresh_cntr + 1; |
|
// |
// BURST LENGTH SELECTOR |
// |
always @(modereg_burst_length) |
case (modereg_burst_length) |
3'b000: modereg_burst_count <= 4'h1; |
3'b001: modereg_burst_count <= 4'h2; |
3'b010: modereg_burst_count <= 4'h4; |
default modereg_burst_count <= 4'h8; |
endcase |
|
|
// |
// REFRESH Request generator |
// |
assign do_refresh = (refresh_state == `state_halt); |
|
|
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
refresh_state <= `state_count; |
refresh_timer <= 8'h00; |
end |
else case (refresh_state) |
// COUNT |
// count up the refresh interval counter. If the |
// timer reaches the refresh-expire time, then go next state |
`state_count: |
if (refresh_timer != `RC) |
refresh_timer <= refresh_timer + 1; |
else |
refresh_state <= `state_halt; |
|
// HALT |
// wait for the SDRAM to complete any ongoing reads or |
// writes. If the SDRAM has acknowledged the do_refresh, |
// (i.e. it is now doing the refresh) |
// then go to next state |
`state_halt: |
if (next_state==`state_auto_refresh | |
next_state==`state_auto_refresh_dly | |
next_state==`state_precharge ) |
refresh_state <= `state_reset; |
|
|
// RESET |
// if the SDRAM refresh is completed, then reset the counter |
// and start counting up again. |
`state_reset: |
if (next_state==`state_idle) begin |
refresh_state <= `state_count; |
refresh_timer <= 8'h00; |
end |
endcase |
|
|
endmodule |
|
/trunk/hostcont.v
0,0 → 1,352
`include "inc.h" |
|
/* |
** HOSTCONT.v |
** |
** This module is the host controller whic sits between the host |
** (usually a micro) and the sdramcnt.v |
** |
** |
** |
** |
*/ |
|
|
module hostcont ( |
// system connections |
sys_rst_l, |
sys_clk, |
|
// microprocessor side connections |
mp_addx, |
mp_data_in, |
mp_data_out, |
mp_rd_l, |
mp_wr_l, |
mp_cs_l, |
sdram_mode_set_l, |
sdram_busy_l, |
|
// SDRAM side connections |
sd_addx, |
sd_data, |
sd_ba, |
sd_wr_l, |
|
// SDRAMCNT side |
sd_addx10_mux, |
sd_addx_mux, |
sd_rd_ena, |
sd_data_ena, |
do_read, |
do_write, |
doing_refresh, |
do_modeset, |
next_state, |
modereg_cas_latency, |
modereg_burst_length, |
mp_data_mux, |
|
// bus type select |
smart_h |
|
// debug |
// rd_wr_clk |
,dumb_busy_out |
,dumb_busy_clk, |
reg_mp_data_mux |
|
); |
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
|
// system connections |
input sys_rst_l; // asynch active low reset |
input sys_clk; // clock source to the SDRAM |
|
// microprocessor side connections |
input [19:0] mp_addx; // 20 bits for the addx |
input [15:0] mp_data_in; // 16 bits of data bus input |
output [15:0] mp_data_out; // 16 bits of data bus output |
input mp_rd_l; // micro bus read , active low |
input mp_wr_l; // micro bus write, active low |
input mp_cs_l; |
input sdram_mode_set_l; // acive low request for SDRAM mode set |
output sdram_busy_l; // active low busy output |
|
// SDRAM side connections |
output [10:0] sd_addx; // 11 bits of muxed SDRAM addx |
inout [15:0] sd_data; // 16 bits of bidirectional SDRAM data bus |
output sd_ba; // bank select output to the SDRAM |
input sd_wr_l; |
|
// SDRAMCNT side |
input [1:0] sd_addx10_mux; |
input [1:0] sd_addx_mux; |
input sd_rd_ena; |
input sd_data_ena; |
output do_write; |
output do_read; |
input doing_refresh; |
output do_modeset; |
input [3:0] next_state; |
output [2:0] modereg_cas_latency; |
output [2:0] modereg_burst_length; |
input mp_data_mux; |
|
// other inputs |
input smart_h; // If high, indicates that writes are non |
// blocking if SDRAM is not busy. Else, |
// all IO are blocked |
|
//debug |
//output rd_wr_clk; |
output dumb_busy_clk; |
output dumb_busy_out; |
output [15:0] reg_mp_data_mux; |
|
// **************************************** |
// |
// Memory Elements |
// |
// **************************************** |
// |
reg [19:0] reg_mp_addx; |
reg [15:0] reg_mp_data; |
reg [15:0] reg_sd_data; |
`ifdef simulate_mp |
wire [10:0] reg_modeset; |
`else |
reg [10:0] reg_modeset; |
`endif |
reg [10:0] sd_addx; |
reg do_read; |
reg do_write; |
reg do_modeset; |
reg sd_ba; |
reg rst_do_write; |
wire [15:0] sd_data; |
wire [15:0] sd_data_buff; |
wire [15:0] reg_mp_data_mux; |
wire [15:0] mp_data_out; |
wire mp_data_ena; |
wire do_read_clk; |
wire do_write_clk; |
wire clock_xx; |
wire modereg_ena; |
wire read_busy; |
wire write_busy; |
wire refresh_busy; |
wire do_write_rst; |
wire dumb_busy_clk; |
wire dumb_busy_rst; |
reg rst_dumb_busy; |
reg dumb_busy_out; |
wire dumb_busy; |
|
|
assign mp_data_out = reg_sd_data; |
assign mp_data_ena = ~mp_rd_l; |
assign modereg_cas_latency = reg_modeset[6:4]; |
assign modereg_burst_length = reg_modeset[2:0]; |
|
assign read_busy = do_read; |
assign write_busy = do_write; |
assign refresh_busy = `LO; |
|
// SDRAM BUSY SIGNAL GENERATION |
// |
// The BUSY signal is NOR'd of READ_BUSY, WRITE_BUSY and DUMB_BUSY. |
// READ_BUSY is generated while the SDRAM is performing a read. This |
// does not necessarily have to he synchronous to the micro's read. |
// The WRITE_BUSY is generated while the SDRAM is performing WRITE. |
// Again, due to the "dump-n-run" mode (only in SMART_H=1) the micro's |
// write bus cycle does not necessarily align with SDRAM's write cycle. |
// DUMB_BUSY is a signal which generates the BUSY at the falling edge of |
// micro's SDRAM_CS. This is used for those microprocessors which |
// require a device BUSY as soon as the address is placed on its bus. For |
// example, most Intel microcontrollers and small processors do have this |
// requirement. This means that one will fofeit on the dump-n-go feature. |
// |
assign sdram_busy_l = ~(read_busy | write_busy | dumb_busy | doing_refresh); |
|
|
// MP ADDRESS LATCH |
// Transparent latch |
// Used to hold the addx from the micro. Latch on the falling edge of |
// mp_rd_l or mp_wr_l |
always @(do_write or sys_rst_l or mp_addx) |
if (~sys_rst_l) |
reg_mp_addx <= 20'h00000; |
else if (~do_write) // hold the addx if do_write==`HI |
reg_mp_addx <= mp_addx; |
else |
reg_mp_addx <= reg_mp_addx; |
|
// MP DATA LATCH |
// Used to hold the data from the micro. Latch on the rising edge |
// of mp_wr_l |
always @(posedge mp_wr_l or negedge sys_rst_l) |
if (~sys_rst_l) |
reg_mp_data <= 16'h0000; |
else if (~mp_cs_l) |
reg_mp_data <= mp_data_in; |
|
|
// MODE REG LATCH |
`ifdef simulate_mp |
assign reg_modeset = 11'h0020; |
`else |
assign modereg_ena = ~mp_cs_l & ~sdram_mode_set_l; |
always @(posedge mp_wr_l or negedge sys_rst_l) |
if (~sys_rst_l) |
reg_modeset <= 11'h0020; // default modeset reg value has this settings: |
// burst length=1, cas latency=2 |
else if (modereg_ena) |
reg_modeset <= mp_data_in; |
`endif |
|
|
// SD DATA LATCH |
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) |
reg_sd_data <= 16'h0000; |
else if (sd_rd_ena) |
reg_sd_data <= sd_data_buff; |
|
|
// SDRAM SIDE ADDX |
always @(sd_addx10_mux or reg_mp_data or reg_mp_addx) |
case (sd_addx10_mux) |
// 2'b00: sd_addx[10] <= 1'b0; |
// 2'b01: sd_addx[10] <= reg_mp_addx[10]; |
2'b00: sd_addx[10] <= reg_mp_addx[18]; |
2'b01: sd_addx[10] <= 1'b0; |
2'b10: sd_addx[10] <= reg_mp_data[10]; |
default: sd_addx[10] <= 1'b1; |
endcase |
|
always @(sd_addx_mux or reg_modeset or reg_mp_addx) |
case (sd_addx_mux) |
// 2'b00: sd_addx[9:0] <= reg_mp_addx[9:0]; |
// 2'b01: sd_addx[9:0] <= {2'b00, reg_mp_addx[18:11]}; |
2'b00: sd_addx[9:0] <= reg_mp_addx[17:8]; // ROW |
2'b01: sd_addx[9:0] <= {2'b00, reg_mp_addx[7:0]}; // COLUMN |
2'b10: sd_addx[9:0] <= reg_modeset[9:0]; |
default: sd_addx[9:0] <= 10'h000; |
endcase |
|
|
// SD_BA |
always @(sd_addx_mux or reg_mp_addx) |
case (sd_addx_mux) |
2'b00: sd_ba <= reg_mp_addx[19]; |
2'b01: sd_ba <= reg_mp_addx[19]; |
default: sd_ba <= 1'b0; |
endcase |
|
|
// SD SIDE DATA BUFFERS |
assign sd_data = sd_data_ena ? reg_mp_data_mux : 16'hzzzz; |
assign sd_data_buff = sd_data; |
|
|
// Micro data mux |
assign reg_mp_data_mux = mp_data_mux ? 16'h0000 : reg_mp_data; |
|
|
// |
// DO_READ signal generation |
// |
// Set by falling edge of mp_rd_l |
// cleared by the falling edge of next_state==`state_read |
assign do_read_clk = ( mp_rd_l | (next_state==`state_read) ); |
always @(negedge do_read_clk or negedge sys_rst_l) |
if (~sys_rst_l) |
do_read <= `LO; |
else |
do_read <= ~do_read; |
|
|
|
// DO_WRITE signal generation logic |
// This signal indicates that the SDRAM is performing a write |
// this is a completely asynchronous logic which does the following: |
// the do_write is |
// set at rising edge of mp_wr_l (at deassertion of micro write bus cycle) |
// cleared on the rising edge of sd_wr_l. That is, at the termination of |
// current SDRAM write cycle. This excludes the sd_wr_l generated during the |
// refresh cycle. |
assign do_write_rst = ~sys_rst_l | rst_do_write; |
always @(posedge mp_wr_l or posedge do_write_rst) |
if (do_write_rst) |
do_write <= `LO; |
else |
do_write <= `HI; |
|
always @(posedge sd_wr_l or posedge do_write_rst) |
if (do_write_rst) |
rst_do_write <= `LO; |
else if (~doing_refresh) // reset only is we're not a refresh cycle |
rst_do_write <= `HI; |
|
|
// |
// DO_MODESET signal generation |
// |
// needs to be triggered by falling edge of |
always @(sys_clk or sys_rst_l) |
if (sys_rst_l) |
do_modeset <= `LO; |
else |
do_modeset <= `LO; |
|
|
|
// |
// DUMB BUSY SIGNAL GENERATION |
// |
// In the "dumb" mode (smart_h == 0), the SDRAM controller will |
// not allow the micro to do another I/O until the |
// present one is finished. The most notable difference is |
// that it will not allow a "dump-&-run" writes. |
// |
// The busy signal is asserted at the falling edge of mp_cs_l. |
// In the case of writes, it is deasserted when mp_rw_l goes low. This |
// allows the micro to deassert its wr (i.e. finish the write bus cycle) |
// at which point the busy is again asserted (since the SDRAM is now being written) |
// until the completion of the write into the SDRAM. |
// During reads, the busy is asserted on the falling edge of mp_cs_l, and is not |
// deasserted until the completion of the read. |
// |
// The busy signal is the or of DO_WRITE , DO_READ as before, but |
// in the smart_h=0 mode, an extra signal dumb_busy_out is also or'd. |
// This signal is set at the falling edge of mp_cs_l. It is cleared |
// on the falling edge of mp_wr_l or on the rising edge of do_read. |
// (mp_wr_l ^ do_read) |
// |
// It is set by the falling edge of MP_CS_L |
// is is cleared by the rising edge of DO_READ or |
// falling edge of mp_WR_L |
assign dumb_busy = (dumb_busy_out & ~smart_h); |
always @(negedge mp_cs_l or posedge dumb_busy_rst) |
if (dumb_busy_rst) |
dumb_busy_out <= `LO; |
else |
dumb_busy_out <= `HI; |
|
assign dumb_busy_rst = ~sys_rst_l | rst_dumb_busy; |
assign dumb_busy_clk = do_read ^ mp_wr_l; |
always @(negedge dumb_busy_clk or posedge dumb_busy_rst) |
if (dumb_busy_rst) |
rst_dumb_busy <= `LO; |
else |
rst_dumb_busy <= `HI; |
|
endmodule |
|
/trunk/tst_inc.h
0,0 → 1,65
// |
// Common Definition File for the SDRAM TEST |
// |
// |
|
|
//******* Allow showing of debug signals |
//`define do_debug |
|
//******* Allow the micro bus model to have queues for read and write |
//`define allow_queue |
|
/* |
** SELECT TEST TO PERFORM |
** Select only one of the below comment |
** |
*/ |
// *************************************************************** |
// This test repeats indefinitely, a write followed by a read. |
// *************************************************************** |
//`define do_read_write_test |
|
|
// *************************************************************** |
// This test does a burst write, followed by a delay (enough to |
// fit a few refresh cycles) then burst read of the same memory |
// areas. This pattern of write-read repeats indefinitely |
// *************************************************************** |
//`define do_burst_write_read_test |
|
|
// *************************************************************** |
// This test does a one time burst write, followed by a delay (enough to |
// fit a few refresh cycles) then burst read of the same memory |
// areas. The burst reads are repeating. |
// *************************************************************** |
//`define do_single_burst_write_read_test |
|
|
// *************************************************************** |
// This test exercises the entire content of the SDRAM. |
// A pseudo-random-number-generator is used to generate the data |
// patern which is written to the SDRAM. Then, the data is read |
// back and compared to the psedo random number. |
// *************************************************************** |
`define do_full_test |
|
// C O M M O N S T U F F |
`define HI 1'b1 |
`define LO 1'b0 |
|
// B U S C O N T R O L L E R |
// This defines the bit width of the bus controller State Machine |
`define MN 3 |
`define MNn `MN-1 |
// This defines the states of the state machine |
`define state_idle `MN'b001 |
`define state_assert_addx `MN'b010 |
`define state_wr_l `MN'b011 |
`define state_wr_h `MN'b110 |
`define state_rd_l `MN'b111 |
`define state_rd_h `MN'b101 |
`define state_deassert_addx `MN'b100 |
`define xxxx `MN'b000 |
|
/trunk/sdram.v
0,0 → 1,375
`include "inc.h" |
|
// |
// SDRAM Controller. |
// |
// Hierarchy: |
// |
// SDRAM.V Wrapper. |
// 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( |
// SYSTEM LEVEL CONNECTIONS |
sys_main_clk, |
sys_rst_l, |
sys_clk, |
|
// SDRAM CONNECTIONS |
sd_clke, |
sd_clk, |
sd_wr_l, |
sd_cs_l, |
sd_ras_l, |
sd_cas_l, |
sd_ldqm, |
sd_udqm, |
sd_addx, |
sd_data, |
sd_ba, |
|
// MICROPORCESSOR CONNECTION |
mp_addx, |
mp_data, |
mp_rd_l, |
mp_wr_l, |
mp_cs_l, |
sdram_mode_set_l, |
sdram_busy_l, |
smart_h, |
|
|
// DEBUG |
`ifdef show_debug |
, |
next_state, |
do_modeset, |
do_read, |
do_write, |
autorefresh_cntr, |
autorefresh_cntr_l, |
pwrup, |
top_state, |
wr_cntr, |
// mp_data_micro, |
reg_mp_data_mux, |
// mp_data_mux, |
sd_data_ena, |
doing_refresh, |
mp_data_out, |
// sd_addx_mux, |
// sd_addx10_mux, |
sd_rd_ena, |
// dumb_busy_clk, |
// dumb_busy_out |
// rd_wr_clk |
`endif |
// simulated micro bus |
`ifdef simulate_mp |
, |
//mp_clk, |
`endif |
|
|
); |
|
|
|
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
// SYSTEM LEVEL CONNECTIONS |
input sys_main_clk; |
input sys_rst_l; |
output sys_clk; |
|
// SDRAM CONNECTIONS |
output sd_clke; |
output sd_clk; |
output sd_wr_l; |
output sd_cs_l; |
output sd_ras_l; |
output sd_cas_l; |
output sd_ldqm; |
output sd_udqm; |
output [10:0] sd_addx; |
inout [15:0] sd_data; |
output sd_ba; |
|
// MICROPORCESSOR CONNECTION |
`ifdef simulate_mp |
output [19:0] mp_addx; |
output mp_rd_l; |
output mp_wr_l; |
output mp_cs_l; |
output [15:0] mp_data; |
`else |
input [19:0] mp_addx; |
input mp_rd_l; |
input mp_wr_l; |
input mp_cs_l; |
inout [15:0] mp_data; |
`endif |
output sdram_busy_l; |
input sdram_mode_set_l; |
input smart_h; |
|
// DEBUG |
`ifdef show_debug |
output [3:0] next_state; |
output do_modeset; |
output do_read; |
output do_write; |
output [12:0] autorefresh_cntr; |
output autorefresh_cntr_l; |
output pwrup; |
output [2:0] top_state; |
output [7:0] wr_cntr; |
//output [15:0] mp_data_micro; |
output [15:0] reg_mp_data_mux; |
output [15:0] mp_data_out; |
//output mp_data_mux; |
output sd_data_ena; |
output doing_refresh; |
//output sd_addx_mux; |
//output sd_addx10_mux; |
output sd_rd_ena; |
//output rd_wr_clk; |
//output dumb_busy_clk; |
//output dumb_busy_out; |
`endif |
|
// simulated micro bus |
`ifdef simulate_mp |
//input mp_clk; |
`endif |
|
|
// INTER-MODULE CONNECTIONS |
wire do_modeset; |
wire do_read; |
wire do_write; |
wire doing_refresh; |
wire sd_addx_ena; |
wire [1:0] sd_addx_mux; |
wire [1:0] sd_addx10_mux; |
wire sd_rd_ena; |
wire sd_data_ena; |
wire [2:0] modereg_cas_latency; |
wire [2:0] modereg_burst_length; |
wire [3:0] next_state; |
wire [15:0] mp_data_out; |
wire [15:0] sd_data; |
wire mp_cs_l; |
wire mp_wr_l; |
wire mp_rd_l; |
wire mp_data_mux; |
wire [12:0] autorefresh_cntr; |
wire autorefresh_cntr_l; |
wire pwrup; |
wire [2:0] top_state; |
|
`ifdef simulate_mp |
wire [19:0] mp_addx; |
wire [15:0] mp_data_inbus; |
wire [15:0] mp_data_micro; |
`endif |
wire sdram_mode_set_l; |
wire sys_clk; |
//wire rd_wr_clk; |
wire sdram_busy_l; |
|
`ifdef simulate_mp |
wire mp_clk; |
`endif |
|
|
`ifdef simulate_mp |
assign mp_data = ~(mp_rd_l | mp_cs_l) ? mp_data_out : mp_data_micro; |
`else |
assign mp_data = ~(mp_rd_l | mp_cs_l) ? mp_data_out : 16'hzzzz; |
`endif |
|
|
/* |
*/ |
// |
// CLOCK GENERATOR |
// |
// |
|
// --divide by 2 |
// |
`ifdef divide_by_2 |
reg sd_clk; |
always @(posedge sys_main_clk) |
sd_clk <= ~sd_clk; |
|
assign sys_clk = sd_clk; |
`endif |
|
// --divide by 4 |
// |
`ifdef divide_by_4 |
reg [1:0] sd_clk; |
always @(posedge sys_main_clk) |
sd_clk <= sd_clk + 2'b01; |
|
assign sys_clk = sd_clk[1]; |
`endif |
|
// --divide by 8 |
// |
`ifdef divide_by_8 |
reg [2:0] sd_clk; |
always @(posedge sys_main_clk) |
sd_clk <= sd_clk + 3'b001; |
|
assign sys_clk = sd_clk[2]; |
`endif |
|
assign mp_clk = sys_clk; |
|
sdramcnt SDRAMCNT( |
// system level stuff |
.sys_rst_l(sys_rst_l), |
.sys_clk(sys_clk), |
|
// SDRAM connections |
.sd_clke(sd_clke), |
.sd_wr_l(sd_wr_l), |
.sd_cs_l(sd_cs_l), |
.sd_ras_l(sd_ras_l), |
.sd_cas_l(sd_cas_l), |
.sd_ldqm(sd_udqm), |
.sd_udqm(sd_ldqm), |
|
// Host Controller connections |
.do_mode_set(do_modeset), |
.do_read(do_read), |
.do_write(do_write), |
.doing_refresh(doing_refresh), |
.sd_addx_mux(sd_addx_mux), |
.sd_addx10_mux(sd_addx10_mux), |
.sd_rd_ena(sd_rd_ena), |
.sd_data_ena(sd_data_ena), |
.modereg_cas_latency(modereg_cas_latency), |
.modereg_burst_length(modereg_burst_length), |
.mp_data_mux(mp_data_mux), |
|
// debug |
.next_state(next_state), |
.autorefresh_cntr(autorefresh_cntr), |
.autorefresh_cntr_l(autorefresh_cntr_l), |
.pwrup(pwrup) |
); |
|
|
hostcont HOSTCONTTT( |
// system connections |
.sys_rst_l(sys_rst_l), |
.sys_clk(sys_clk), |
|
// microprocessor side connections |
.mp_addx(mp_addx), |
`ifdef simulate_mp |
.mp_data_in(mp_data_micro), |
`else |
.mp_data_in(mp_data), |
`endif |
.mp_data_out(mp_data_out), |
.mp_rd_l(mp_rd_l), |
.mp_wr_l(mp_wr_l), |
.mp_cs_l(mp_cs_l), |
.sdram_mode_set_l(sdram_mode_set_l), |
.sdram_busy_l(sdram_busy_l), |
|
// SDRAM side connections |
.sd_addx(sd_addx), |
.sd_data(sd_data), |
.sd_ba(sd_ba), |
.sd_wr_l(sd_wr_l), |
|
// SDRAMCNT side |
.sd_addx10_mux(sd_addx10_mux), |
.sd_addx_mux(sd_addx_mux), |
.sd_rd_ena(sd_rd_ena), |
.sd_data_ena(sd_data_ena), |
.do_read(do_read), |
.do_write(do_write), |
.doing_refresh(doing_refresh), |
.do_modeset(do_modeset), |
.modereg_cas_latency(modereg_cas_latency), |
.modereg_burst_length(modereg_burst_length), |
.next_state(next_state), |
.mp_data_mux(mp_data_mux), |
|
// other inputs |
.smart_h(smart_h) |
|
// debug |
// .rd_wr_clk(rd_wr_clk) |
,.dumb_busy_clk(dumb_busy_clk), |
.dumb_busy_out(dumb_busy_out), |
.reg_mp_data_mux(reg_mp_data_mux) |
); |
|
|
`ifdef simulate_mp |
micro MICRO ( |
// system connections |
.mp_clk(mp_clk), |
.sys_rst_l(sys_rst_l), |
|
// Connections to the SDRAM CONTROLLER |
.sdram_busy_l(sdram_busy_l), |
.mp_addx(mp_addx), |
.mp_data(mp_data_micro), |
.mp_wr_l(mp_wr_l), |
.mp_rd_l(mp_rd_l), |
.mp_cs_l(mp_cs_l), |
.next_state(next_state), |
|
// debug |
.top_state(top_state), |
.wr_cntr(wr_cntr) |
|
); |
|
`endif |
|
endmodule |
|
// |
// REVISION LOG |
// |
// 7/31/99 |
// Added/tested/debugged support for interfacing to Intel type of |
// Microprocessors, where it is required that the device "busy" be asserted |
// when the chip_select decoded. That is before it is known whether it is |
// a read or a write cycle |
// This is called the "non-smart" interface, where all bus request from the |
// micro is blocked until it is completed. It is enabled by pulling low |
// on the smart_h pin. |
// |
// |
// 8/15/99 |
// Made the width of the AutoRefresh Command to be 1+ CLKs. By just having it |
// to be 1 CLK, the burst reads (back to back 1 word reads, not SDRAM "burst" reads) |
// would be all messed up if a refresh happened to coem in the middle. By making |
// the refresh command to be more than 1 CLK (2 or more) this problem was |
// eliminated. |
// |
/trunk/micro.v
0,0 → 1,366
`include "tst_inc.h" |
`include "inc.h" |
module micro( |
// system connections |
mp_clk, |
sys_rst_l, |
|
// Connections to the HOSTCONT.V |
sdram_busy_l, |
mp_addx, |
mp_data, |
mp_wr_l, |
mp_rd_l, |
mp_cs_l, |
|
next_state, |
|
// debug |
top_state, |
wr_cntr |
|
); |
|
|
|
// system connections |
input mp_clk; // main system clock |
input sys_rst_l; // main system reset |
|
// connections to the SDRAM CONTROLLER |
input sdram_busy_l; |
output [19:0] mp_addx; |
output mp_wr_l; |
output mp_rd_l; |
output mp_cs_l; |
input [3:0] next_state; |
output [15:0] mp_data; |
|
// debug |
output [2:0] top_state; |
output [7:0] wr_cntr; |
|
// Intermodule connections |
wire [7:0] bus_state; |
wire data_ena; |
wire [15:0] mp_data; |
wire mp_wr_l; |
wire mp_rd_l; |
wire mp_cs_l; |
|
|
// Memory element definitions |
reg req_wr_l; |
reg req_rd_l; |
reg change_addx; |
reg data_addx_rst_l; |
|
// INSTANTIATE THE MICRO BUS |
sim_mp SIM_MP( |
// system connections |
.mp_clk(mp_clk), |
.sys_rst_l(sys_rst_l), |
|
// inputs |
.req_wr_l(req_wr_l), |
.req_rd_l(req_rd_l), |
.sdram_busy_l(sdram_busy_l), |
.change_addx(change_addx), |
.data_addx_rst_l(data_addx_rst_l), |
|
// outputs |
.mp_addx(mp_addx), |
.mp_data(mp_data), |
.mp_wr_l(mp_wr_l), |
.mp_rd_l(mp_rd_l), |
.mp_cs_l(mp_cs_l), |
.state(bus_state), |
.data_ena(data_ena) |
|
); |
|
|
/* |
** SINGLE WRITE FOLLOWED BY GAP THEN FOLLOWED BY SINGLE READ TEST |
** |
*/ |
`ifdef do_read_write_test |
`define NN 8 |
`define NNn `NN-1 |
`define delay `NN'h20 |
reg [2:0] top_state; |
reg [`NNn:0] cntr; |
reg rst_cntr; |
`define do_read 3'h0 |
`define do_write 3'h1 |
`define do_read_wait 3'h2 |
`define do_write_wait 3'h3 |
`define do_wait 3'h4 |
`define powerup_wait 3'h5 |
|
// Top level state machie |
always @(posedge mp_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
req_wr_l <= `HI; // do not request any writes |
req_rd_l <= `HI; // do not request any reads |
change_addx <= `LO; // do not change addx |
top_state <= `powerup_wait; |
rst_cntr <= `HI; |
data_addx_rst_l <= `LO; // reset the data and addx counters |
cntr <= `NN'h00; // initialize the counter |
end |
else case (top_state) |
`powerup_wait: begin |
data_addx_rst_l <= `HI; // allow the data and addx to count up |
if (next_state == `state_idle) |
top_state <= `do_write; |
end |
|
`do_write: begin |
change_addx <= `HI; // tell bus controller to increment addx/data |
req_wr_l <= `LO; // request a micro write |
top_state <= `do_write_wait; |
end |
|
`do_write_wait: begin |
change_addx <= `LO; // done incrementing addx/data |
req_wr_l <= `HI; // done requesting the write |
if (bus_state == `state_deassert_addx) begin |
top_state <= `do_wait; |
rst_cntr <= `LO; |
end |
end |
|
`do_wait: begin |
if (cntr == `delay) begin |
top_state <= `do_read; |
rst_cntr <= `HI; |
cntr <= `NN'h00; // reset the counter |
end |
cntr <= cntr + 1; // increment the counter |
end |
|
`do_read: begin |
req_rd_l <= `LO; // request a read from the micro simulator |
top_state <= `do_read_wait; |
end |
|
`do_read_wait: begin |
req_rd_l <= `HI; // done requesting the read |
if (bus_state == `state_deassert_addx) begin |
top_state <= `do_write; |
end |
end |
endcase |
|
|
// Counter to count the events |
always @(posedge mp_clk or posedge rst_cntr) |
if (rst_cntr) |
cntr <= 8'h000; |
else |
cntr <= cntr + 1; |
|
|
`endif |
|
|
/* |
** BURST WRITE FOLLOWED BY GAP THEN FOLLOWED BY BURST READ TEST |
** |
*/ |
`ifdef do_burst_write_read_test |
`define MN 8 |
`define MNn `MN-1 |
`define RW_COUNT `MN'h20 |
`define GAP_DELAY `MN'h40 |
reg [2:0] top_state; |
reg rst_cntr; |
//reg [`XY-1:0] cntr; |
reg [`MNn:0] wr_cntr; |
`define powerup_delay 3'h1 |
`define burst_write 3'h2 |
`define burst_write_wait 3'h3 |
`define write_read_delay 3'h4 |
`define burst_read 3'h5 |
`define burst_read_wait 3'h6 |
|
|
always @(posedge mp_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
top_state <= `powerup_delay; |
req_wr_l <= `HI; // do not request any writes |
req_rd_l <= `HI; // do not request any reads |
change_addx <= `LO; // do not change addx |
rst_cntr <= `HI; // reset counter |
wr_cntr <= `MN'h00; |
data_addx_rst_l <= `LO; // reset the data and addx counter |
end |
else case (top_state) |
`powerup_delay: begin |
data_addx_rst_l <= `HI; // allow the data and the addx couter to count up |
if (next_state == `state_idle) begin |
top_state <= `burst_write; // go and do burst write |
end |
end |
|
`burst_write: begin |
req_wr_l <= `LO; // request a write |
top_state <= `burst_write_wait; |
change_addx <= `LO; // done changing addx |
end |
|
`burst_write_wait: begin |
req_wr_l <= `HI; // done requesting a write |
if (bus_state == `state_deassert_addx) begin |
if (wr_cntr == `RW_COUNT) begin |
top_state <= `write_read_delay; // go and do reads |
rst_cntr <= `LO; // allow counter to go up |
wr_cntr <= `MN'h00; // clear write counter |
end else begin |
wr_cntr <= wr_cntr + `MN'h1; |
change_addx <= `HI; // increment addx |
top_state <= `burst_write; |
end |
end |
end |
|
// Wait for a bit to allow several refrehes into the SDRAM |
`write_read_delay: begin |
if (wr_cntr == `GAP_DELAY) begin |
data_addx_rst_l <= `HI; // allow the data and the addx couter to count up |
rst_cntr <= `HI; // reset counter |
wr_cntr <= `MN'h00; // clear write counter |
top_state <= `burst_read; |
end else begin |
wr_cntr <= wr_cntr + `MN'h1; // count up by one |
data_addx_rst_l <= `LO; // reset the data and addx counters |
end |
end |
|
`burst_read: begin |
req_rd_l <= `LO; // request read |
top_state <= `burst_read_wait; |
change_addx <= `LO; // done changing addx |
end |
|
`burst_read_wait: begin |
req_rd_l <= `HI; // done requesting a read |
if (bus_state == `state_deassert_addx) begin |
if(wr_cntr == `RW_COUNT) begin |
data_addx_rst_l <= `LO; // reset the addx and data couters |
top_state <= `powerup_delay; |
wr_cntr <= 5'h00; // clear write counter |
end else begin |
top_state <= `burst_read; |
change_addx <= `HI; // inc addx |
wr_cntr <= wr_cntr + 1; |
end |
end |
end |
endcase |
|
`endif |
|
|
/* |
** A ONE-TIME BURST WRITE FOLLOWED BY GAP THEN FOLLOWED BY MANY BURST READ TEST |
** |
*/ |
`ifdef do_single_burst_write_read_test |
|
`define MN 8 |
`define RW_COUNT 8'h5 |
`define GAP_DELAY 8'h10 |
|
reg [2:0] top_state; |
reg rst_cntr; |
reg [7:0] wr_cntr; |
|
`define powerup_delay 3'h1 |
`define burst_write 3'h2 |
`define burst_write_wait 3'h3 |
`define write_read_delay 3'h4 |
`define burst_read 3'h5 |
`define burst_read_wait 3'h6 |
|
|
always @(posedge mp_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
top_state <= `powerup_delay; |
req_wr_l <= `HI; // do not request any writes |
req_rd_l <= `HI; // do not request any reads |
change_addx <= `LO; // do not change addx |
rst_cntr <= `HI; // reset counter |
wr_cntr <= 8'h00; // reset the cycle counter |
data_addx_rst_l <= `LO; // reset the data and addx counter |
end |
else case (top_state) |
`powerup_delay: begin |
if (next_state == `state_idle) begin |
top_state <= `burst_write;// go and do burst write |
end else |
data_addx_rst_l <= `HI; // allow the data and the addx couter to count up |
end |
|
`burst_write: begin |
req_wr_l <= `LO; // request a write |
top_state <= `burst_write_wait; |
change_addx <= `LO; // done changing addx |
end |
|
`burst_write_wait: begin |
req_wr_l <= `HI; // done requesting a write |
if (bus_state == `state_deassert_addx) begin |
if (wr_cntr == `RW_COUNT) begin |
top_state <= `write_read_delay; // go and do reads |
rst_cntr <= `LO; // allow counter to go up |
data_addx_rst_l <= `LO; // reset the data and addx counters |
wr_cntr <= 8'h00; |
end else begin |
wr_cntr <= wr_cntr + 8'h1; |
top_state <= `burst_write; |
change_addx <= `HI; // increment addx |
end |
end |
end |
|
// Wait for a bit to allow several refrehes into the SDRAM |
`write_read_delay: begin |
if (wr_cntr == `GAP_DELAY) begin |
data_addx_rst_l <= `HI; // allow the data and the addx couter to count up |
rst_cntr <= `HI; // reset counter |
wr_cntr <= 8'h00; |
top_state <= `burst_read; |
end else |
wr_cntr <= wr_cntr + 8'h1; |
end |
|
`burst_read: begin |
req_rd_l <= `LO; // request read |
top_state <= `burst_read_wait; |
change_addx <= `LO; // done changing addx |
end |
|
`burst_read_wait: begin |
req_rd_l <= `HI; // done requesting a read |
if (bus_state == `state_deassert_addx) begin |
if(wr_cntr == `RW_COUNT) begin |
data_addx_rst_l <= `LO; // reset the addx and data couters |
top_state <= `write_read_delay; |
wr_cntr <= 8'h00; |
end else begin |
wr_cntr <= wr_cntr + 1; |
top_state <= `burst_read; |
change_addx <= `HI; // inc addx |
end |
end |
end |
endcase |
|
|
`endif |
|
|
endmodule |
|