OpenFPGA/openfpga_flow/benchmarks/iwls2005/mem_ctrl/rtl/mc_timing.v

1736 lines
41 KiB
Verilog

/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE Memory Controller Main Timing Block ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: mc_timing.v,v 1.8 2002/01/21 13:08:52 rudi Exp $
//
// $Date: 2002/01/21 13:08:52 $
// $Revision: 1.8 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: mc_timing.v,v $
// Revision 1.8 2002/01/21 13:08:52 rudi
//
// Fixed several minor bugs, cleaned up the code further ...
//
// Revision 1.7 2001/12/21 05:09:30 rudi
//
// - Fixed combinatorial loops in synthesis
// - Fixed byte select bug
//
// Revision 1.6 2001/12/11 02:47:19 rudi
//
// - Made some changes not to expect clock during reset ...
//
// Revision 1.5 2001/11/29 02:16:28 rudi
//
//
// - More Synthesis cleanup, mostly for speed
// - Several bug fixes
// - Changed code to avoid auto-precharge and
// burst-terminate combinations (apparently illegal ?)
// Now we will do a manual precharge ...
//
// Revision 1.4 2001/09/24 00:38:21 rudi
//
// Changed Reset to be active high and async.
//
// Revision 1.3 2001/09/02 02:28:28 rudi
//
// Many fixes for minor bugs that showed up in gate level simulations.
//
// Revision 1.2 2001/08/10 08:16:21 rudi
//
// - Changed IO names to be more clear.
// - Uniquifyed define names to be core specific.
// - Removed "Refresh Early" configuration
//
// Revision 1.1 2001/07/29 07:34:41 rudi
//
//
// 1) Changed Directory Structure
// 2) Fixed several minor bugs
//
// Revision 1.4 2001/06/14 01:57:37 rudi
//
//
// Fixed a potential bug in a corner case situation where the TMS register
// does not propegate properly during initialisation.
//
// Revision 1.3 2001/06/12 15:19:49 rudi
//
//
// Minor changes after running lint, and a small bug fix reading csr and ba_mask registers.
//
// Revision 1.2 2001/06/03 11:37:17 rudi
//
//
// 1) Fixed Chip Select Mask Register
// - Power On Value is now all ones
// - Comparison Logic is now correct
//
// 2) All resets are now asynchronous
//
// 3) Converted Power On Delay to an configurable item
//
// 4) Added reset to Chip Select Output Registers
//
// 5) Forcing all outputs to Hi-Z state during reset
//
// Revision 1.1.1.1 2001/05/13 09:39:44 rudi
// Created Directory Structure
//
//
//
//
`include "mc_defines.v"
module mc_timing(clk, rst,
// Wishbone Interface
wb_cyc_i, wb_stb_i, wb_we_i,
wb_read_go, wb_write_go, wb_first, wb_wait, mem_ack,
err,
// Suspend/Resume Interface
susp_req, resume_req, suspended, susp_sel,
// Memory Interface
mc_clk, data_oe, oe_, we_, cas_, ras_, cke_,
cs_en, wb_cycle, wr_cycle,
mc_br, mc_bg, mc_adsc, mc_adv,
mc_c_oe, mc_ack,
not_mem_cyc,
// Register File Interface
csc, tms, cs, lmr_req, lmr_ack, cs_le_d, cs_le,
// Address Select Signals
cmd_a10, row_sel, next_adr, page_size,
// OBCT Signals
bank_set, bank_clr, bank_clr_all, bank_open, any_bank_open, row_same,
// Data path Controller Signals
dv, pack_le0, pack_le1, pack_le2, par_err,
// Refresh Counter Signals
rfr_req, rfr_ack,
// Initialize Request & Ack
init_req, init_ack
);
input clk;
input rst;
// Wishbone Interface
input wb_cyc_i, wb_stb_i, wb_we_i;
input wb_read_go;
input wb_write_go;
input wb_first;
input wb_wait;
output mem_ack;
output err;
// Suspend/Resume Interface
input susp_req;
input resume_req;
output suspended;
output susp_sel;
// Memory Interface
input mc_clk;
output data_oe;
output oe_;
output we_;
output cas_;
output ras_;
output cke_;
output cs_en;
output wb_cycle;
output wr_cycle;
input mc_br;
output mc_bg;
output mc_adsc;
output mc_adv;
output mc_c_oe;
input mc_ack;
input not_mem_cyc;
// Register File Interface
input [31:0] csc;
input [31:0] tms;
input [7:0] cs;
input lmr_req;
output lmr_ack;
output cs_le;
output cs_le_d;
// Address Select Signals
input [10:0] page_size;
output cmd_a10;
output row_sel;
output next_adr;
// OBCT Signals
output bank_set;
output bank_clr;
output bank_clr_all;
input bank_open;
input any_bank_open;
input row_same;
// Data path Controller Signals
output dv;
output pack_le0, pack_le1, pack_le2; // Pack Latch Enable
input par_err;
// Refresh Counter Signals
input rfr_req;
output rfr_ack;
// Initialize Request & Ack
input init_req;
output init_ack;
////////////////////////////////////////////////////////////////////
//
// Defines & Parameters
//
// Number of states: 66
parameter [65:0] // synopsys enum state
// 6666666555555555544444444443333333333222222222211111111110000000000
// 6543210987654321098765432109876543210987654321098765432109876543210
POR = 66'b000000000000000000000000000000000000000000000000000000000000000001,
IDLE = 66'b000000000000000000000000000000000000000000000000000000000000000010,
IDLE_T = 66'b000000000000000000000000000000000000000000000000000000000000000100,
IDLE_T2 = 66'b000000000000000000000000000000000000000000000000000000000000001000,
PRECHARGE = 66'b000000000000000000000000000000000000000000000000000000000000010000,
PRECHARGE_W = 66'b000000000000000000000000000000000000000000000000000000000000100000,
ACTIVATE = 66'b000000000000000000000000000000000000000000000000000000000001000000,
ACTIVATE_W = 66'b000000000000000000000000000000000000000000000000000000000010000000,
SD_RD_WR = 66'b000000000000000000000000000000000000000000000000000000000100000000,
SD_RD = 66'b000000000000000000000000000000000000000000000000000000001000000000,
SD_RD_W = 66'b000000000000000000000000000000000000000000000000000000010000000000,
SD_RD_LOOP = 66'b000000000000000000000000000000000000000000000000000000100000000000,
SD_RD_W2 = 66'b000000000000000000000000000000000000000000000000000001000000000000,
SD_WR = 66'b000000000000000000000000000000000000000000000000000010000000000000,
SD_WR_W = 66'b000000000000000000000000000000000000000000000000000100000000000000,
BT = 66'b000000000000000000000000000000000000000000000000001000000000000000,
BT_W = 66'b000000000000000000000000000000000000000000000000010000000000000000,
REFR = 66'b000000000000000000000000000000000000000000000000100000000000000000,
LMR0 = 66'b000000000000000000000000000000000000000000000001000000000000000000,
LMR1 = 66'b000000000000000000000000000000000000000000000010000000000000000000,
LMR2 = 66'b000000000000000000000000000000000000000000000100000000000000000000,
// 6666666555555555544444444443333333333222222222211111111110000000000
// 6543210987654321098765432109876543210987654321098765432109876543210
INIT0 = 66'b000000000000000000000000000000000000000000001000000000000000000000,
INIT = 66'b000000000000000000000000000000000000000000010000000000000000000000,
INIT_W = 66'b000000000000000000000000000000000000000000100000000000000000000000,
INIT_REFR1 = 66'b000000000000000000000000000000000000000001000000000000000000000000,
INIT_REFR1_W = 66'b000000000000000000000000000000000000000010000000000000000000000000,
// 6666666555555555544444444443333333333222222222211111111110000000000
// 6543210987654321098765432109876543210987654321098765432109876543210
INIT_LMR = 66'b000000000000000000000000000000000000000100000000000000000000000000,
SUSP1 = 66'b000000000000000000000000000000000000001000000000000000000000000000,
SUSP2 = 66'b000000000000000000000000000000000000010000000000000000000000000000,
SUSP3 = 66'b000000000000000000000000000000000000100000000000000000000000000000,
SUSP4 = 66'b000000000000000000000000000000000001000000000000000000000000000000,
RESUME1 = 66'b000000000000000000000000000000000010000000000000000000000000000000,
RESUME2 = 66'b000000000000000000000000000000000100000000000000000000000000000000,
BG0 = 66'b000000000000000000000000000000001000000000000000000000000000000000,
BG1 = 66'b000000000000000000000000000000010000000000000000000000000000000000,
BG2 = 66'b000000000000000000000000000000100000000000000000000000000000000000,
ACS_RD = 66'b000000000000000000000000000001000000000000000000000000000000000000,
ACS_RD1 = 66'b000000000000000000000000000010000000000000000000000000000000000000,
ACS_RD2A = 66'b000000000000000000000000000100000000000000000000000000000000000000,
ACS_RD2 = 66'b000000000000000000000000001000000000000000000000000000000000000000,
ACS_RD3 = 66'b000000000000000000000000010000000000000000000000000000000000000000,
ACS_RD_8_1 = 66'b000000000000000000000000100000000000000000000000000000000000000000,
ACS_RD_8_2 = 66'b000000000000000000000001000000000000000000000000000000000000000000,
ACS_RD_8_3 = 66'b000000000000000000000010000000000000000000000000000000000000000000,
ACS_RD_8_4 = 66'b000000000000000000000100000000000000000000000000000000000000000000,
ACS_RD_8_5 = 66'b000000000000000000001000000000000000000000000000000000000000000000,
ACS_RD_8_6 = 66'b000000000000000000010000000000000000000000000000000000000000000000,
ACS_WR = 66'b000000000000000000100000000000000000000000000000000000000000000000,
ACS_WR1 = 66'b000000000000000001000000000000000000000000000000000000000000000000,
ACS_WR2 = 66'b000000000000000010000000000000000000000000000000000000000000000000,
ACS_WR3 = 66'b000000000000000100000000000000000000000000000000000000000000000000,
ACS_WR4 = 66'b000000000000001000000000000000000000000000000000000000000000000000,
SRAM_RD = 66'b000000000000010000000000000000000000000000000000000000000000000000,
SRAM_RD0 = 66'b000000000000100000000000000000000000000000000000000000000000000000,
SRAM_RD1 = 66'b000000000001000000000000000000000000000000000000000000000000000000,
SRAM_RD2 = 66'b000000000010000000000000000000000000000000000000000000000000000000,
SRAM_RD3 = 66'b000000000100000000000000000000000000000000000000000000000000000000,
SRAM_RD4 = 66'b000000001000000000000000000000000000000000000000000000000000000000,
SRAM_WR = 66'b000000010000000000000000000000000000000000000000000000000000000000,
SRAM_WR0 = 66'b000000100000000000000000000000000000000000000000000000000000000000,
SCS_RD = 66'b000001000000000000000000000000000000000000000000000000000000000000,
SCS_RD1 = 66'b000010000000000000000000000000000000000000000000000000000000000000,
SCS_RD2 = 66'b000100000000000000000000000000000000000000000000000000000000000000,
SCS_WR = 66'b001000000000000000000000000000000000000000000000000000000000000000,
SCS_WR1 = 66'b010000000000000000000000000000000000000000000000000000000000000000,
SCS_ERR = 66'b100000000000000000000000000000000000000000000000000000000000000000;
////////////////////////////////////////////////////////////////////
//
// Local Registers & Wires
//
reg [65:0] /* synopsys enum state */ state, next_state;
// synopsys state_vector state
reg mc_bg;
wire [2:0] mem_type;
wire [1:0] bus_width;
wire kro;
wire cs_a;
reg [3:0] cmd;
wire mem_ack;
wire mem_ack_s;
reg mem_ack_d;
reg err_d;
wire err;
reg cmd_a10;
reg lmr_ack;
reg lmr_ack_d;
reg row_sel;
reg oe_;
reg oe_d;
reg data_oe;
reg data_oe_d;
reg cke_d;
reg cke_;
reg init_ack;
reg dv;
reg rfr_ack_d;
reg mc_adsc;
reg mc_adv;
reg bank_set;
reg bank_clr;
reg bank_clr_all;
reg wr_set, wr_clr;
reg wr_cycle;
reg cmd_asserted;
reg cmd_asserted2;
reg [10:0] burst_val;
reg [10:0] burst_cnt;
wire burst_act;
reg burst_act_rd;
wire single_write;
reg cs_le_d;
reg cs_le;
reg cs_le_r;
reg susp_req_r;
reg resume_req_r;
reg suspended;
reg suspended_d;
reg susp_sel_set, susp_sel_clr, susp_sel_r;
reg [3:0] cmd_del;
reg [3:0] cmd_r;
reg data_oe_r;
reg data_oe_r2;
reg cke_r;
reg cke_rd;
reg cke_o_del;
reg cke_o_r1;
reg cke_o_r2;
reg wb_cycle_set, wb_cycle;
reg [3:0] ack_cnt;
wire ack_cnt_is_0;
reg cnt, cnt_next;
reg [7:0] timer;
reg tmr_ld_trp, tmr_ld_trcd, tmr_ld_tcl, tmr_ld_trfc;
reg tmr_ld_twr, tmr_ld_txsr;
reg tmr2_ld_tscsto;
reg tmr_ld_trdv;
reg tmr_ld_trdz;
reg tmr_ld_twr2;
wire timer_is_zero;
reg tmr_done;
reg tmr2_ld_trdv, tmr2_ld_trdz;
reg tmr2_ld_twpw, tmr2_ld_twd, tmr2_ld_twwd;
reg tmr2_ld_tsrdv;
reg [8:0] timer2;
reg tmr2_done;
wire timer2_is_zero;
reg [3:0] ir_cnt;
reg ir_cnt_ld;
reg ir_cnt_dec;
reg ir_cnt_done;
reg rfr_ack_r;
reg burst_cnt_ld;
reg burst_fp;
reg wb_wait_r, wb_wait_r2;
reg lookup_ready1, lookup_ready2;
reg burst_cnt_ld_4;
reg dv_r;
reg mc_adv_r1, mc_adv_r;
reg next_adr;
reg pack_le0, pack_le1, pack_le2;
reg pack_le0_d, pack_le1_d, pack_le2_d;
wire bw8, bw16;
reg mc_c_oe_d;
reg mc_c_oe;
reg mc_le;
reg mem_ack_r;
reg rsts, rsts1;
reg no_wb_cycle;
wire bc_dec;
reg ap_en; // Auto Precharge Enable
reg cmd_a10_r;
reg wb_stb_first;
reg tmr_ld_tavav;
////////////////////////////////////////////////////////////////////
//
// Aliases
//
assign mem_type = csc[3:1];
assign bus_width = csc[5:4];
assign kro = csc[10];
assign single_write = tms[9] | (tms[2:0] == 3'h0);
////////////////////////////////////////////////////////////////////
//
// Misc Logic
//
reg cs_le_r1;
always @(posedge clk)
lmr_ack <= #1 lmr_ack_d;
assign rfr_ack = rfr_ack_r;
always @(posedge clk)
cs_le_r <= #1 cs_le_r1;
always @(posedge clk)
cs_le_r1 <= #1 cs_le;
always @(posedge clk)
cs_le <= #1 cs_le_d;
always @(posedge mc_clk or posedge rst)
if(rst) rsts1 <= #1 1'b1;
else rsts1 <= #1 1'b0;
always @(posedge clk or posedge rst)
if(rst) rsts <= #1 1'b1;
else rsts <= #1 rsts1;
// Control Signals Output Enable
always @(posedge clk or posedge rst)
if(rst) mc_c_oe <= #1 1'b0;
else mc_c_oe <= #1 mc_c_oe_d;
always @(posedge clk or posedge rsts)
if(rsts) mc_le <= #1 1'b0;
else mc_le <= #1 ~mc_le;
always @(posedge clk)
pack_le0 <= #1 pack_le0_d;
always @(posedge clk)
pack_le1 <= #1 pack_le1_d;
always @(posedge clk)
pack_le2 <= #1 pack_le2_d;
always @(posedge clk or posedge rst)
if(rst) mc_adv_r1 <= #1 1'b0;
else
if(!mc_le) mc_adv_r1 <= #1 mc_adv;
always @(posedge clk or posedge rst)
if(rst) mc_adv_r <= #1 1'b0;
else
if(!mc_le) mc_adv_r <= #1 mc_adv_r1;
// Bus Width decoder
assign bw8 = (bus_width == `MC_BW_8);
assign bw16 = (bus_width == `MC_BW_16);
// Any Chip Select
assign cs_a = |cs;
// Memory to Wishbone Ack
assign mem_ack = (mem_ack_d | mem_ack_s) & (wb_read_go | wb_write_go);
always @(posedge clk or posedge rst)
if(rst) mem_ack_r <= #1 1'b0;
else mem_ack_r <= #1 mem_ack;
assign err = err_d;
// SDRAM Command, either delayed (for writes) or straight through
always @(posedge clk or posedge rst)
if(rst) cmd_r <= #1 `MC_CMD_NOP;
else cmd_r <= #1 cmd;
always @(posedge clk or posedge rst)
if(rst) cmd_del <= #1 `MC_CMD_NOP;
else cmd_del <= #1 cmd_r;
assign {cs_en, ras_, cas_, we_} = wr_cycle ? cmd_del : cmd;
// Track Timing of Asserting a command
always @(posedge clk or posedge rst)
if(rst) cmd_asserted <= #1 1'b0;
else
if(!mc_le) cmd_asserted <= #1 cmd[3];
always @(posedge clk or posedge rst)
if(rst) cmd_asserted2 <= #1 1'b0;
else
if(!mc_le) cmd_asserted2 <= #1 cmd_asserted;
// Output Enable
always @(posedge clk or posedge rst)
if(rst) oe_ <= #1 1'b1;
else oe_ <= #1 ~oe_d;
// Memory Bus Data lines Output Enable
always @(posedge clk or posedge rst)
if(rst) data_oe_r <= #1 1'b0;
else data_oe_r <= #1 data_oe_d;
always @(posedge clk or posedge rst)
if(rst) data_oe_r2 <= #1 1'b0;
else data_oe_r2 <= #1 data_oe_r;
always @(posedge clk or posedge rst)
if(rst) data_oe <= #1 1'b0;
else data_oe <= #1 wr_cycle ? data_oe_r2 : data_oe_d;
// Clock Enable
always @(posedge clk)
cke_r <= #1 cke_d;
always @(posedge clk)
cke_ <= #1 cke_r & cke_rd;
// CKE output delay line to time DV for reads
always @(posedge clk)
cke_o_r1 <= #1 cke_;
always @(posedge clk)
cke_o_r2 <= #1 cke_o_r1;
always @(posedge clk)
cke_o_del <= #1 cke_o_r2;
// Delayed version of the wb_wait input
always @(posedge clk)
wb_wait_r2 <= #1 wb_wait;
always @(posedge clk)
wb_wait_r <= #1 wb_wait_r2;
// Indicates when the row_same and bank_open lookups are done
reg lookup_ready1a;
always @(posedge clk or posedge rst)
if(rst) lookup_ready1 <= #1 1'b0;
else lookup_ready1 <= #1 cs_le & wb_cyc_i & wb_stb_i;
always @(posedge clk or posedge rst)
if(rst) lookup_ready2 <= #1 1'b0;
else lookup_ready2 <= #1 lookup_ready1 & wb_cyc_i & wb_stb_i;
// Keep Track if it is a SDRAM write cycle
always @(posedge clk or posedge rst)
if(rst) wr_cycle <= #1 1'b0;
else
if(wr_set) wr_cycle <= #1 1'b1;
else
if(wr_clr) wr_cycle <= #1 1'b0;
// Track when a cycle is *still* active
always @(posedge clk or posedge rst)
if(rst) wb_cycle <= #1 1'b0;
else
if(wb_cycle_set) wb_cycle <= #1 1'b1;
else
if(!wb_cyc_i | not_mem_cyc) wb_cycle <= #1 1'b0;
// Thses two signals are used to signal that no wishbone cycle is in
// progress. Need to register them to avoid a very long combinatorial
// path ....
always @(posedge clk or posedge rst)
if(rst) no_wb_cycle <= #1 1'b0;
else no_wb_cycle <= #1 !wb_read_go & !wb_write_go;
// Track ack's for read cycles
always @(posedge clk or posedge rst)
if(rst) ack_cnt <= #1 4'h0;
else
if(no_wb_cycle) ack_cnt <= #1 4'h0;
else
if(dv & !mem_ack_s) ack_cnt <= #1 ack_cnt + 4'h1;
else
if(!dv & mem_ack_s) ack_cnt <= #1 ack_cnt - 4'h1;
assign ack_cnt_is_0 = (ack_cnt==4'h0);
assign mem_ack_s = (ack_cnt != 4'h0) & !wb_wait & !mem_ack_r & wb_read_go & !(wb_we_i & wb_stb_i);
// Internal Cycle Tracker
always @(posedge clk)
cnt <= #1 cnt_next;
// Suspend/resume Logic
always @(posedge clk or posedge rst)
if(rst) susp_req_r <= #1 1'b0;
else susp_req_r <= #1 susp_req;
always @(posedge clk or posedge rst)
if(rst) resume_req_r <= #1 1'b0;
else resume_req_r <= #1 resume_req;
always @(posedge clk or posedge rst)
if(rst) suspended <= #1 1'b0;
else suspended <= #1 suspended_d;
always @(posedge clk or posedge rst)
if(rst) rfr_ack_r <= #1 1'b0;
else rfr_ack_r <= #1 rfr_ack_d;
// Suspend Select Logic
assign susp_sel = susp_sel_r;
always @(posedge clk or posedge rst)
if(rst) susp_sel_r <= #1 1'b0;
else
if(susp_sel_set) susp_sel_r <= #1 1'b1;
else
if(susp_sel_clr) susp_sel_r <= #1 1'b0;
////////////////////////////////////////////////////////////////////
//
// Timing Logic
//
wire [3:0] twrp;
wire twd_is_zero;
wire [31:0] tms_x;
// FIX_ME
// Hard wire worst case or make it programmable ???
assign tms_x = (rfr_ack_d | rfr_ack_r | susp_sel | !mc_c_oe) ? 32'hffff_ffff : tms;
always @(posedge clk)
if(tmr2_ld_tscsto) timer2 <= #1 tms_x[24:16];
else
if(tmr2_ld_tsrdv) timer2 <= #1 9'd4; // SSRAM RD->1st DATA VALID
else
if(tmr2_ld_twpw) timer2 <= #1 { 5'h0, tms_x[15:12]};
else
if(tmr2_ld_twd) timer2 <= #1 { 4'h0, tms_x[19:16],1'b0};
else
if(tmr2_ld_twwd) timer2 <= #1 { 3'h0, tms_x[25:20]};
else
if(tmr2_ld_trdz) timer2 <= #1 { 4'h0, tms_x[11:8], 1'b1};
else
if(tmr2_ld_trdv) timer2 <= #1 { tms_x[7:0], 1'b1};
else
if(!timer2_is_zero) timer2 <= #1 timer2 - 9'b1;
assign twd_is_zero = (tms_x[19:16] == 4'h0);
assign timer2_is_zero = (timer2 == 9'h0);
always @(posedge clk or posedge rst)
if(rst) tmr2_done <= #1 1'b0;
else tmr2_done <= #1 timer2_is_zero & !tmr2_ld_trdv & !tmr2_ld_trdz &
!tmr2_ld_twpw & !tmr2_ld_twd & !tmr2_ld_twwd & !tmr2_ld_tscsto;
assign twrp = {2'h0,tms_x[16:15]} + tms_x[23:20];
// SDRAM Memories timing tracker
always @(posedge clk or posedge rst)
`ifdef MC_POR_DELAY
if(rst) timer <= #1 `MC_POR_DELAY_VAL ;
else
`endif
if(tmr_ld_twr2) timer <= #1 { 4'h0, tms_x[15:12] };
else
if(tmr_ld_trdz) timer <= #1 { 4'h0, tms_x[11:8] };
else
if(tmr_ld_trdv) timer <= #1 tms_x[7:0];
else
if(tmr_ld_twr) timer <= #1 { 4'h0, twrp};
else
if(tmr_ld_trp) timer <= #1 { 4'h0, tms_x[23:20]};
else
if(tmr_ld_trcd) timer <= #1 { 5'h0, tms_x[19:17]};
else
if(tmr_ld_tcl) timer <= #1 { 6'h0, tms_x[05:04]};
else
if(tmr_ld_trfc) timer <= #1 { 4'h0, tms_x[27:24]};
else
if(tmr_ld_tavav) timer <= #1 8'h3;
else
if(tmr_ld_txsr) timer <= #1 8'h7;
else
if(!timer_is_zero & !mc_le) timer <= #1 timer - 8'b1;
assign timer_is_zero = (timer == 8'h0);
always @(posedge clk or posedge rst)
if(rst) tmr_done <= #1 1'b0;
else tmr_done <= #1 timer_is_zero;
// Init Refresh Cycles Counter
always @(posedge clk)
if(ir_cnt_ld) ir_cnt <= #1 `MC_INIT_RFRC_CNT;
else
if(ir_cnt_dec) ir_cnt <= #1 ir_cnt - 4'b1;
always @(posedge clk)
ir_cnt_done <= #1 (ir_cnt == 4'h0);
// Burst Counter
always @(tms_x or page_size)
case(tms_x[2:0]) // synopsys full_case parallel_case
3'h0: burst_val = 11'h1;
3'h1: burst_val = 11'h2;
3'h2: burst_val = 11'h4;
3'h3: burst_val = 11'h8;
3'h7: burst_val = page_size;
endcase
assign bc_dec = wr_cycle ? mem_ack_d : dv;
always @(posedge clk)
if(burst_cnt_ld_4) burst_cnt <= #1 11'h4; // for SSRAM only
else
if(burst_cnt_ld) burst_cnt <= #1 burst_val;
else
if(bc_dec) burst_cnt <= #1 burst_cnt - 11'h1;
always @(posedge clk or posedge rst)
if(rst) burst_fp <= #1 1'b0;
else
if(burst_cnt_ld) burst_fp <= #1 (tms_x[2:0] == 3'h7);
// Auto Precharge Enable
always @(posedge clk or posedge rst)
if(rst) ap_en <= #1 1'b0;
else
if(burst_cnt_ld) ap_en <= #1 (tms_x[2:0] == 3'h0) & !kro;
assign burst_act = |burst_cnt & ( |tms_x[2:0] );
always @(posedge clk)
burst_act_rd <= #1 |burst_cnt;
always @(posedge clk or posedge rst)
if(rst) dv_r <= #1 1'b0;
else dv_r <= #1 dv;
always @(posedge clk) // Auto Precharge Holding Register
cmd_a10_r <= #1 cmd_a10;
////////////////////////////////////////////////////////////////////
//
// Main State Machine
//
reg wb_write_go_r;
always @(posedge clk)
wb_write_go_r <= #1 wb_write_go;
always @(posedge clk or posedge rst)
if(rst) wb_stb_first <= #1 1'b0;
else
if(mem_ack) wb_stb_first <= #1 1'b0;
else
if(wb_first & wb_stb_i) wb_stb_first <= #1 1'b1;
always @(posedge clk or posedge rst)
`ifdef MC_POR_DELAY
if(rst) state <= #1 POR;
`else
if(rst) state <= #1 IDLE;
`endif
else state <= #1 next_state;
always @(state or cs_a or cs_le or cs_le_r or
twd_is_zero or wb_stb_i or wb_write_go_r or
wb_first or wb_read_go or wb_write_go or wb_wait or mem_ack_r or wb_we_i or
ack_cnt_is_0 or wb_wait_r or cnt or wb_cycle or wr_cycle or
mem_type or kro or lookup_ready2 or row_same or cmd_a10_r or
bank_open or single_write or
cmd_asserted or tmr_done or tmr2_done or ir_cnt_done or cmd_asserted2 or
burst_act or burst_act_rd or burst_fp or cke_ or cke_r or cke_o_del or
rfr_req or lmr_req or init_req or rfr_ack_r or susp_req_r or resume_req_r or
mc_br or bw8 or bw16 or dv_r or mc_adv_r or mc_ack or wb_stb_first or ap_en
)
begin
next_state = state; // Default keep current state
cnt_next = 1'b0;
cmd = `MC_CMD_NOP;
cmd_a10 = ap_en;
oe_d = 1'b0;
data_oe_d = 1'b0;
cke_d = 1'b1;
cke_rd = 1'b1;
mc_adsc = 1'b0;
mc_adv = 1'b0;
bank_set = 1'b0;
bank_clr = 1'b0;
bank_clr_all = 1'b0;
burst_cnt_ld = 1'b0;
burst_cnt_ld_4 = 1'b0;
tmr_ld_trp = 1'b0;
tmr_ld_trcd = 1'b0;
tmr_ld_tcl = 1'b0;
tmr_ld_trfc = 1'b0;
tmr_ld_twr = 1'b0;
tmr_ld_txsr = 1'b0;
tmr_ld_trdv = 1'b0;
tmr_ld_trdz = 1'b0;
tmr_ld_twr2 = 1'b0;
tmr_ld_tavav = 1'b0;
tmr2_ld_trdv = 1'b0;
tmr2_ld_trdz = 1'b0;
tmr2_ld_twpw = 1'b0;
tmr2_ld_twd = 1'b0;
tmr2_ld_twwd = 1'b0;
tmr2_ld_tsrdv = 1'b0;
tmr2_ld_tscsto = 1'b0;
mem_ack_d = 1'b0;
err_d = 1'b0;
rfr_ack_d = 1'b0;
lmr_ack_d = 1'b0;
init_ack = 1'b0;
ir_cnt_dec = 1'b0;
ir_cnt_ld = 1'b0;
row_sel = 1'b0;
cs_le_d = 1'b0;
wr_clr = 1'b0;
wr_set = 1'b0;
wb_cycle_set = 1'b0;
dv = 1'b0;
suspended_d = 1'b0;
susp_sel_set = 1'b0;
susp_sel_clr = 1'b0;
mc_bg = 1'b0;
next_adr = 1'b0;
pack_le0_d = 1'b0;
pack_le1_d = 1'b0;
pack_le2_d = 1'b0;
mc_c_oe_d = 1'b1;
case(state) // synopsys full_case parallel_case
`ifdef MC_POR_DELAY
POR:
begin
if(tmr_done) next_state = IDLE;
end
`endif
IDLE:
begin
//cs_le_d = wb_stb_first | lmr_req;
cs_le_d = wb_stb_first;
burst_cnt_ld = 1'b1;
wr_clr = 1'b1;
if(mem_type == `MC_MEM_TYPE_SCS) tmr2_ld_tscsto = 1'b1;
if(mem_type == `MC_MEM_TYPE_SRAM) tmr2_ld_tsrdv = 1'b1;
if(rfr_req)
begin
rfr_ack_d = 1'b1;
next_state = PRECHARGE;
end
else
if(init_req)
begin
cs_le_d = 1'b1;
next_state = INIT0;
end
else
if(lmr_req & lookup_ready2)
begin
lmr_ack_d = 1'b1;
cs_le_d = 1'b1;
next_state = LMR0;
end
else
if(susp_req_r & !wb_cycle)
begin
cs_le_d = 1'b1;
susp_sel_set = 1'b1;
next_state = SUSP1;
end
else
if(cs_a & (wb_read_go | wb_write_go) & lookup_ready2)
begin
wb_cycle_set = 1'b1;
case(mem_type) // synopsys full_case parallel_case
`MC_MEM_TYPE_SDRAM: // SDRAM
if((lookup_ready2) & !wb_wait)
begin
if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1;
if(kro & bank_open & row_same) next_state = SD_RD_WR;
else
if(kro & bank_open) next_state = PRECHARGE;
else next_state = ACTIVATE;
end
`MC_MEM_TYPE_ACS:
begin // Async Chip Select
if(!wb_wait)
begin
cs_le_d = 1'b1;
if(wb_write_go)
begin
data_oe_d = 1'b1;
next_state = ACS_WR;
end
else next_state = ACS_RD;
end
end
`MC_MEM_TYPE_SCS:
begin // Sync Chip Select
if(!wb_wait)
begin
cs_le_d = 1'b1;
if(wb_write_go)
begin
cmd = `MC_CMD_XWR;
data_oe_d = 1'b1;
tmr_ld_twr2 = 1'b1;
next_state = SCS_WR;
end
else
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr_ld_trdv = 1'b1;
next_state = SCS_RD;
end
end
end
`MC_MEM_TYPE_SRAM:
begin // SRAM
if(!wb_wait)
begin
cs_le_d = 1'b1;
if(wb_write_go)
begin
data_oe_d = 1'b1;
mem_ack_d = 1'b1;
next_state = SRAM_WR;
end
else
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
mc_adsc = 1'b1;
next_state = SRAM_RD;
end
end
end
endcase
end
else
if(mc_br)
begin
if(!cmd_asserted2)
begin
next_state = BG0;
mc_c_oe_d = 1'b0;
end
end
end
IDLE_T:
begin
cmd_a10 = cmd_a10_r; // Hold Auto Precharge 'til cycle finishes
if(tmr_done & wb_cycle & !wb_wait) cs_le_d = 1'b1;
if(tmr_done) next_state = IDLE;
end
IDLE_T2:
begin
if(tmr2_done & (!wb_wait | !wb_cycle) )
begin
cs_le_d = wb_cycle;
if(cs_le_r | !wb_cycle) next_state = IDLE;
end
end
/////////////////////////////////////////
// SCS STATES ....
/////////////////////////////////////////
SCS_RD:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr_ld_trdv = 1'b1;
if(mc_ack) next_state = SCS_RD1;
else
if(tmr2_done) next_state = SCS_ERR;
end
SCS_RD1:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
if(tmr_done)
begin
mem_ack_d = 1'b1;
tmr_ld_trdz = 1'b1;
next_state = SCS_RD2;
end
end
SCS_RD2:
begin
tmr_ld_trdz = 1'b1;
next_state = IDLE_T;
end
SCS_WR:
begin
tmr_ld_twr2 = 1'b1;
cmd = `MC_CMD_XWR;
data_oe_d = 1'b1;
if(mc_ack) next_state = SCS_WR1;
else
if(tmr2_done) next_state = SCS_ERR;
end
SCS_WR1:
begin
data_oe_d = 1'b1;
if(tmr_done)
begin
mem_ack_d = 1'b1;
next_state = IDLE_T;
end
else cmd = `MC_CMD_XWR;
end
SCS_ERR:
begin
mem_ack_d = 1'b1;
err_d = 1'b1;
next_state = IDLE_T2;
end
/////////////////////////////////////////
// SSRAM STATES ....
/////////////////////////////////////////
SRAM_RD:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
mc_adsc = 1'b1;
tmr2_ld_tsrdv = 1'b1;
burst_cnt_ld_4 = 1'b1;
if(cmd_asserted) next_state = SRAM_RD0;
end
SRAM_RD0:
begin
mc_adv = 1'b1;
oe_d = 1'b1;
if(tmr2_done)
begin
mc_adv = !wb_wait;
next_state = SRAM_RD1;
end
end
SRAM_RD1:
begin
if(mc_adv_r) dv = ~dv_r;
mc_adv = !wb_wait;
if(!burst_act | !wb_read_go) next_state = SRAM_RD2;
else oe_d = 1'b1;
end
SRAM_RD2:
begin
if(ack_cnt_is_0 & wb_read_go) next_state = SRAM_RD3;
else
if(!wb_read_go)
begin
mc_adsc = 1'b1;
next_state = SRAM_RD4;
end
end
SRAM_RD3:
begin
if(!wb_read_go)
begin
mc_adsc = 1'b1;
next_state = SRAM_RD4;
end
else
if(!wb_wait)
begin
cs_le_d = 1'b1;
next_state = SRAM_RD;
end
end
SRAM_RD4: // DESELECT
begin
if(wb_cycle) cs_le_d = 1'b1; // For RMW
mc_adsc = 1'b1;
next_state = IDLE;
end
SRAM_WR:
begin
cmd = `MC_CMD_XWR;
mc_adsc = 1'b1;
data_oe_d = 1'b1;
if(cmd_asserted)
begin
if(wb_wait) next_state = SRAM_WR0;
else
if(!wb_write_go)
begin
mc_adsc = 1'b1;
next_state = SRAM_RD4;
end
else
begin
data_oe_d = 1'b1;
mem_ack_d = ~mem_ack_r;
end
end
end
SRAM_WR0:
begin
if(wb_wait) next_state = SRAM_WR0;
else
if(!wb_write_go)
begin
mc_adsc = 1'b1;
next_state = SRAM_RD4;
end
else
begin
data_oe_d = 1'b1;
next_state = SRAM_WR;
end
end
/////////////////////////////////////////
// Async Devices STATES ....
/////////////////////////////////////////
ACS_RD:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr2_ld_trdv = 1'b1;
next_state = ACS_RD1;
end
ACS_RD1:
begin // 32 bit, 8 bit - first; 16 bit - first
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
if(tmr2_done)
begin
if(bw8 | bw16) next_adr = 1'b1;
if(bw8) next_state = ACS_RD_8_1;
else
if(bw16) next_state = ACS_RD_8_5;
else next_state = ACS_RD2A;
end
end
ACS_RD_8_1:
begin // 8 bit 2nd byte
pack_le0_d = 1'b1;
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr2_ld_trdv = 1'b1;
next_state = ACS_RD_8_2;
end
ACS_RD_8_2:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
if(tmr2_done)
begin
next_adr = 1'b1;
next_state = ACS_RD_8_3;
end
end
ACS_RD_8_3:
begin // 8 bit 3rd byte
pack_le1_d = 1'b1;
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr2_ld_trdv = 1'b1;
next_state = ACS_RD_8_4;
end
ACS_RD_8_4:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
if(tmr2_done)
begin
next_adr = 1'b1;
next_state = ACS_RD_8_5;
end
end
ACS_RD_8_5:
begin // 8 bit 4th byte; 16 bit 2nd word
if(bw8) pack_le2_d = 1'b1;
if(bw16) pack_le0_d = 1'b1;
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
tmr2_ld_trdv = 1'b1;
next_state = ACS_RD_8_6;
end
ACS_RD_8_6:
begin
cmd = `MC_CMD_XRD;
oe_d = 1'b1;
if(tmr2_done)
begin
next_state = ACS_RD2;
end
end
ACS_RD2A:
begin
oe_d = 1'b1;
cmd = `MC_CMD_XRD;
next_state = ACS_RD2;
end
ACS_RD2:
begin
cmd = `MC_CMD_XRD;
next_state = ACS_RD3;
end
ACS_RD3:
begin
mem_ack_d = 1'b1;
tmr2_ld_trdz = 1'b1;
next_state = IDLE_T2;
end
ACS_WR:
begin
tmr2_ld_twpw = 1'b1;
cmd = `MC_CMD_XWR;
data_oe_d = 1'b1;
next_state = ACS_WR1;
end
ACS_WR1:
begin
if(!cmd_asserted) tmr2_ld_twpw = 1'b1;
cmd = `MC_CMD_XWR;
data_oe_d = 1'b1;
if(tmr2_done)
begin
tmr2_ld_twd = 1'b1;
next_state = ACS_WR2;
end
end
ACS_WR2:
begin
if(twd_is_zero) next_state = ACS_WR3;
else
begin
cmd = `MC_CMD_XRD;
data_oe_d = 1'b1;
next_state = ACS_WR3;
end
end
ACS_WR3:
begin
if(tmr2_done) next_state = ACS_WR4;
else cmd = `MC_CMD_XRD;
end
ACS_WR4:
begin
tmr2_ld_twwd = 1'b1;
mem_ack_d = 1'b1;
next_state = IDLE_T2;
end
/////////////////////////////////////////
// SDRAM STATES ....
/////////////////////////////////////////
PRECHARGE:
begin
cmd = `MC_CMD_PC;
if(rfr_ack_r)
begin
rfr_ack_d = 1'b1;
cmd_a10 = `MC_ALL_BANKS;
bank_clr_all = 1'b1;
end
else
begin
bank_clr = 1'b1;
cmd_a10 = `MC_SINGLE_BANK;
end
tmr_ld_trp = 1'b1;
if(cmd_asserted) next_state = PRECHARGE_W;
end
PRECHARGE_W:
begin
rfr_ack_d = rfr_ack_r;
if(tmr_done)
begin
if(rfr_ack_r) next_state = REFR;
else next_state = ACTIVATE;
end
end
ACTIVATE:
begin
if(!wb_wait_r)
begin
row_sel = 1'b1;
tmr_ld_trcd = 1'b1;
cmd = `MC_CMD_ACT;
end
if(cmd_asserted) next_state = ACTIVATE_W;
end
ACTIVATE_W:
begin
row_sel = 1'b1;
if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1;
if(kro) bank_set = 1'b1;
if(tmr_done)
begin
if(wb_write_go)
begin
mem_ack_d = ~mem_ack_r;
cmd_a10 = ap_en | (single_write & !kro);
next_state = SD_WR;
end
else
if(!wb_wait_r) next_state = SD_RD;
end
end
SD_RD_WR:
begin
if(wb_write_go | (wb_we_i & wb_stb_i)) wr_set = 1'b1;
if(wb_write_go & !wb_wait)
begin // Write
data_oe_d = 1'b1;
mem_ack_d = ~mem_ack_r;
cmd_a10 = ap_en | (single_write & !kro);
next_state = SD_WR;
end
else
if(!wb_wait)
begin // Read
if(kro)
begin
if(!wb_wait_r) next_state = SD_RD;
end
else next_state = SD_RD;
end
end
SD_WR: // Write Command
begin // Does the first single write
data_oe_d = 1'b1;
tmr_ld_twr = 1'b1;
cnt_next = ~cnt;
cmd = `MC_CMD_WR;
cmd_a10 = ap_en | (single_write & !kro);
if(!cnt & wb_cycle & burst_act) cke_d = ~wb_wait;
else cke_d = cke_r;
if(cmd_asserted)
begin
mem_ack_d = !mem_ack_r & wb_write_go & !wb_wait & wb_cycle & burst_act;
if(wb_cycle & !burst_act) next_state = IDLE_T;
else
if(wb_write_go) next_state = SD_WR_W;
else
if(burst_act & !single_write) next_state = BT;
else
if(!ap_en) next_state = BT_W;
else next_state = IDLE_T;
end
end
SD_WR_W:
begin // Does additional Writes or Times them
tmr_ld_twr = 1'b1;
cnt_next = ~cnt;
if(single_write & wb_cycle)
begin
cmd = `MC_CMD_WR;
end
cmd_a10 = ap_en | (single_write & !kro);
data_oe_d = 1'b1;
mem_ack_d = !mem_ack_r & wb_write_go & !wb_wait & wr_cycle & burst_act;
if(!cnt) cke_d = ~wb_wait;
else cke_d = cke_r;
if( (single_write & cke_r) | (!single_write & !cnt & !wb_wait) | (!single_write & cnt & cke_r) )
begin
if(single_write & !wb_cycle) next_state = IDLE_T;
else
if(burst_act & !single_write & !wb_write_go_r)
begin
cmd = `MC_CMD_BT;
next_state = BT;
end
else
if(!burst_act & !ap_en) next_state = BT_W;
else
if(!burst_act) next_state = IDLE_T;
else
if(!wb_write_go_r & wb_read_go) next_state = IDLE_T; // Added for WMR
end
end
SD_RD: // Read Command
begin
cmd = `MC_CMD_RD;
cmd_a10 = ap_en;
tmr_ld_tcl = 1'b1;
if(cmd_asserted) next_state = SD_RD_W;
end
SD_RD_W:
begin
if(tmr_done) next_state = SD_RD_LOOP;
end
SD_RD_LOOP:
begin
cnt_next = ~cnt;
if(cnt & !(burst_act & !wb_cycle) & burst_act ) cke_rd = !wb_wait;
else cke_rd = cke_;
if(wb_cycle & !cnt & burst_act_rd & cke_o_del) dv = 1'b1;
if(wb_cycle & wb_write_go) next_state = BT;
else
if(burst_act & !wb_cycle) next_state = BT;
else
if(!burst_act) next_state = SD_RD_W2;
end
SD_RD_W2:
begin
if(wb_write_go | ack_cnt_is_0)
begin
if(!ap_en & !kro) next_state = BT_W;
else
if(!wb_wait & !mem_ack_r) next_state = IDLE_T;
end
end
BT:
begin
cmd = `MC_CMD_BT;
tmr_ld_trp = 1'b1;
if(cmd_asserted) next_state = BT_W;
end
BT_W:
begin
cmd_a10 = cmd_a10_r; // Hold Auto Precharge 'til cycle finishes
if(kro & tmr_done)
begin
if(kro & !wb_wait & (wb_read_go | wb_write_go) ) cs_le_d = 1'b1;
next_state = IDLE;
end
else
if(!kro & tmr_done) // Must do a PRECHARGE after Burst Terminate
begin
bank_clr = 1'b1;
cmd = `MC_CMD_PC;
cmd_a10 = `MC_SINGLE_BANK;
tmr_ld_trp = 1'b1;
if(cmd_asserted) next_state = IDLE_T;
end
end
REFR: // Refresh Cycle
begin
cs_le_d = 1'b1;
cmd = `MC_CMD_ARFR;
tmr_ld_trfc = 1'b1;
rfr_ack_d = 1'b1;
if(cmd_asserted)
begin
susp_sel_clr = 1'b1;
next_state = IDLE_T;
end
end
LMR0:
begin
lmr_ack_d = 1'b1;
cmd = `MC_CMD_PC;
cmd_a10 = `MC_ALL_BANKS;
bank_clr_all = 1'b1;
tmr_ld_trp = 1'b1;
if(cmd_asserted) next_state = LMR1;
end
LMR1:
begin
lmr_ack_d = 1'b1;
if(tmr_done) next_state = LMR2;
end
LMR2:
begin
bank_clr_all = 1'b1;
cmd = `MC_CMD_LMR;
tmr_ld_trfc = 1'b1;
lmr_ack_d = 1'b1;
if(cmd_asserted) next_state = IDLE_T;
end
INIT0:
begin
cs_le_d = 1'b1;
next_state = INIT;
end
INIT: // Initialize SDRAMS
begin // PRECHARGE
init_ack = 1'b1;
cmd = `MC_CMD_PC;
cmd_a10 = `MC_ALL_BANKS;
bank_clr_all = 1'b1;
tmr_ld_trp = 1'b1;
ir_cnt_ld = 1'b1;
if(cmd_asserted) next_state = INIT_W;
end
INIT_W:
begin
init_ack = 1'b1;
if(tmr_done) next_state = INIT_REFR1;
end
INIT_REFR1: // Init Refresh Cycle 1
begin
init_ack = 1'b1;
cmd = `MC_CMD_ARFR;
tmr_ld_trfc = 1'b1;
if(cmd_asserted)
begin
ir_cnt_dec = 1'b1;
next_state = INIT_REFR1_W;
end
end
INIT_REFR1_W:
begin
init_ack = 1'b1;
if(tmr_done)
begin
if(ir_cnt_done) next_state = INIT_LMR;
else next_state = INIT_REFR1;
end
end
INIT_LMR:
begin
init_ack = 1'b1;
cmd = `MC_CMD_LMR;
bank_clr_all = 1'b1;
tmr_ld_trfc = 1'b1;
if(cmd_asserted) next_state = IDLE_T;
end
/////////////////////////////////////////
// Bus Arbitration STATES ....
/////////////////////////////////////////
BG0:
begin // Bus Grant
mc_bg = 1'b1;
mc_c_oe_d = 1'b0;
next_state = BG1;
end
BG1:
begin // Bus Grant
mc_bg = 1'b1;
cs_le_d = 1'b1;
mc_c_oe_d = 1'b0;
next_state = BG2;
end
BG2:
begin // Bus Grant
cs_le_d = 1'b1;
mc_bg = !wb_read_go & !wb_write_go &
!rfr_req & !init_req & !lmr_req &
!susp_req_r;
tmr_ld_tavav = 1'b1;
mc_c_oe_d = mc_br;
if(!mc_br) next_state = IDLE_T;
end
/////////////////////////////////////////
// SUSPEND/RESUME STATES ....
/////////////////////////////////////////
SUSP1:
begin // Precharge All
cmd = `MC_CMD_PC;
cmd_a10 = `MC_ALL_BANKS;
bank_clr_all = 1'b1;
tmr_ld_trp = 1'b1;
if(cmd_asserted) next_state = SUSP2;
end
SUSP2:
begin
if(tmr_done) next_state = SUSP3;
end
SUSP3:
begin // Enter Self refresh Mode
cke_d = 1'b0;
cmd = `MC_CMD_ARFR;
rfr_ack_d = 1'b1;
if(cmd_asserted)
begin
next_state = SUSP4;
end
end
SUSP4:
begin // Now we are suspended
cke_rd = 1'b0;
suspended_d = 1'b1;
tmr_ld_txsr = 1'b1;
if(resume_req_r) next_state = RESUME1;
end
RESUME1:
begin
suspended_d = 1'b1;
tmr_ld_txsr = 1'b1;
next_state = RESUME2;
end
RESUME2:
begin
suspended_d = 1'b1;
if(tmr_done) next_state = REFR;
end
// synopsys translate_off
default:
$display("MC_TIMING SM: Entered non existing state ... (%t)",$time);
// synopsys translate_on
endcase
end
endmodule