diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/Kickman.sdc b/Arcade_MiST/Midway MCR 1/Kickman_MiST/Kickman.sdc
index fca44902..4f80488a 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/Kickman.sdc
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/Kickman.sdc
@@ -87,8 +87,8 @@ set_input_delay -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk
#**************************************************************
set_output_delay -add_delay -clock_fall -clock [get_clocks {SPI_SCK}] 1.000 [get_ports {SPI_DO}]
-set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] 1.000 [get_ports {AUDIO_L}]
-set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] 1.000 [get_ports {AUDIO_R}]
+set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] 1.000 [get_ports {AUDIO_L}]
+set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] 1.000 [get_ports {AUDIO_R}]
set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] 1.000 [get_ports {LED}]
set_output_delay -add_delay -clock_fall -clock [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] 1.000 [get_ports {VGA_*}]
@@ -116,9 +116,6 @@ set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks
set_multicycle_path -to {VGA_*[*]} -setup 2
set_multicycle_path -to {VGA_*[*]} -hold 1
-set_multicycle_path -from [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -to [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -setup 2
-set_multicycle_path -from [get_clocks {pll|altpll_component|auto_generated|pll1|clk[0]}] -to [get_clocks {pll|altpll_component|auto_generated|pll1|clk[1]}] -hold 1
-
#**************************************************************
# Set Maximum Delay
#**************************************************************
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/README.txt b/Arcade_MiST/Midway MCR 1/Kickman_MiST/README.txt
index 8370a324..72ce28a1 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/README.txt
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/README.txt
@@ -4,6 +4,10 @@
-- 3 November 2019
--
-- VGA Only
+-- KICKMAN.ROM file : Main ROM + Sound ROM
+-- 1200-a-ur.b3 + 1300-b-ur.b4 + 1400-c-ur.b5 + 1500-d-ur.d4 + 1600-e-ur.d5 + 1700-f-ur.d6 +
+-- 4200-a.a7 + 4300-b.a8 + 4400-c.a9 + 4500-d.a10
+
---------------------------------------------------------------------------------
-- DE10_lite Top level for Kick (Midway MCR) by Dar (darfpga@aol.fr) (19/10/2019)
-- http://darfpga.blogspot.fr
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/Release/KICKMAN.ROM b/Arcade_MiST/Midway MCR 1/Kickman_MiST/Release/KICKMAN.ROM
index 8fc0d5fe..9ecbd5b6 100644
Binary files a/Arcade_MiST/Midway MCR 1/Kickman_MiST/Release/KICKMAN.ROM and b/Arcade_MiST/Midway MCR 1/Kickman_MiST/Release/KICKMAN.ROM differ
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/Kickman_MiST.sv b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/Kickman_MiST.sv
index 7f7eab8b..54eff27a 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/Kickman_MiST.sv
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/Kickman_MiST.sv
@@ -59,6 +59,7 @@ localparam CONF_STR = {
assign LED = ~ioctl_downl;
assign SDRAM_CLK = clk_sys;
+assign SDRAM_CKE = 1;
wire clk_sys;
wire pll_locked;
@@ -83,6 +84,9 @@ wire [3:0] g, r, b;
wire [14:0] rom_addr;
wire [15:0] rom_do;
wire rom_rd;
+wire [13:0] snd_addr;
+wire [15:0] snd_do;
+wire snd_rd;
wire ioctl_downl;
wire [7:0] ioctl_index;
wire ioctl_wr;
@@ -100,20 +104,57 @@ data_io data_io(
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_dout )
);
-
-sdram cart(
+
+reg port1_req, port2_req;
+sdram sdram(
.*,
- .init ( ~pll_locked ),
+ .init_n ( pll_locked ),
.clk ( clk_sys ),
- .wtbt ( 2'b00 ),
- .dout ( rom_do ),
- .din ( {ioctl_dout, ioctl_dout} ),
- .addr ( ioctl_downl ? ioctl_addr : rom_addr ),
- .we ( ioctl_downl & ioctl_wr ),
- .rd ( !ioctl_downl & rom_rd),
- .ready()
+
+ // port1 used for main CPU
+ .port1_req ( port1_req ),
+ .port1_ack (),
+ .port1_a ( ioctl_downl ? ioctl_addr[23:1] : rom_addr[14:1] ),
+ .port1_ds ( ioctl_downl ? {ioctl_addr[0], ~ioctl_addr[0]} : 2'b11 ),
+ .port1_we ( ioctl_downl ),
+ .port1_d ( {ioctl_dout, ioctl_dout} ),
+ .port1_q ( rom_do ),
+
+ // port2 for sound board
+ .port2_req ( port2_req ),
+ .port2_ack (),
+ .port2_a ( ioctl_downl ? ioctl_addr[23:1] - 16'h3000 : snd_addr[13:1] ),
+ .port2_ds ( ioctl_downl ? {ioctl_addr[0], ~ioctl_addr[0]} : 2'b11 ),
+ .port2_we ( ioctl_downl ),
+ .port2_d ( {ioctl_dout, ioctl_dout} ),
+ .port2_q ( snd_do )
);
+always @(posedge clk_sys) begin
+ reg [14:1] rom_addr_last;
+ reg [13:1] snd_addr_last;
+ reg ioctl_wr_last = 0;
+
+ ioctl_wr_last <= ioctl_wr;
+ if (ioctl_downl) begin
+ snd_addr_last <= 13'h1fff;
+ rom_addr_last <= 14'h3fff;
+ if (~ioctl_wr_last && ioctl_wr) begin
+ port1_req <= ~port1_req;
+ port2_req <= ~port2_req;
+ end
+ end else begin
+ if (rom_rd && rom_addr_last != rom_addr[14:1]) begin
+ rom_addr_last <= rom_addr[14:1];
+ port1_req <= ~port1_req;
+ end
+ if (snd_rd && snd_addr_last != snd_addr[13:1]) begin
+ snd_addr_last <= snd_addr[13:1];
+ port2_req <= ~port2_req;
+ end
+ end
+end
+
reg reset = 1;
reg rom_loaded = 0;
always @(posedge clk_sys) begin
@@ -146,8 +187,11 @@ kick kick(
.btn_left(m_left),
.btn_right(m_right),
.cpu_rom_addr ( rom_addr ),
- .cpu_rom_do ( rom_do[7:0] ),
- .cpu_rom_rd ( rom_rd )
+ .cpu_rom_do ( rom_addr[0] ? rom_do[15:8] : rom_do[7:0] ),
+ .cpu_rom_rd ( rom_rd ),
+ .snd_rom_addr ( snd_addr ),
+ .snd_rom_do ( snd_addr[0] ? snd_do[15:8] : snd_do[7:0] ),
+ .snd_rom_rd ( snd_rd )
);
mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video(
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick.vhd b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick.vhd
index e6579dd5..e7474216 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick.vhd
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick.vhd
@@ -171,7 +171,11 @@ port(
dbg_cpu_addr : out std_logic_vector(15 downto 0);
cpu_rom_addr : out std_logic_vector(14 downto 0);
cpu_rom_do : in std_logic_vector(7 downto 0);
- cpu_rom_rd : out std_logic
+ cpu_rom_rd : out std_logic;
+
+ snd_rom_addr : out std_logic_vector(13 downto 0);
+ snd_rom_do : in std_logic_vector(7 downto 0);
+ snd_rom_rd : out std_logic
);
end kick;
@@ -744,7 +748,7 @@ port map(
);
cpu_rom_addr <= cpu_addr(14 downto 0);
-cpu_rom_rd <= '1' when cpu_mreq_n = '0' and cpu_addr(15 downto 12) < X"7" else '0';
+cpu_rom_rd <= '1' when cpu_mreq_n = '0' and cpu_rd_n = '0' and cpu_addr(15 downto 12) < X"7" else '0';
-- working RAM 0x7000-0x77FF
wram : entity work.gen_ram
@@ -880,6 +884,10 @@ port map(
audio_out_l => audio_out_l,
audio_out_r => audio_out_r,
+ cpu_rom_addr => snd_rom_addr,
+ cpu_rom_do => snd_rom_do,
+ cpu_rom_rd => snd_rom_rd,
+
dbg_cpu_addr => open --dbg_cpu_addr
);
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick_sound_board.vhd b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick_sound_board.vhd
index bccea4eb..ca00dc07 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick_sound_board.vhd
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/kick_sound_board.vhd
@@ -71,7 +71,11 @@ port(
audio_out_l : out std_logic_vector(15 downto 0);
audio_out_r : out std_logic_vector(15 downto 0);
-
+
+ cpu_rom_addr : out std_logic_vector(13 downto 0);
+ cpu_rom_do : in std_logic_vector(7 downto 0);
+ cpu_rom_rd : out std_logic;
+
dbg_cpu_addr : out std_logic_vector(15 downto 0)
);
end kick_sound_board;
@@ -98,7 +102,7 @@ architecture struct of kick_sound_board is
signal cpu_irq_n : std_logic;
signal cpu_m1_n : std_logic;
- signal cpu_rom_do : std_logic_vector( 7 downto 0);
+-- signal cpu_rom_do : std_logic_vector( 7 downto 0);
signal wram_we : std_logic;
signal wram_do : std_logic_vector( 7 downto 0);
@@ -430,12 +434,15 @@ port map(
);
-- cpu program ROM 0x0000-0x3FFF
-rom_cpu : entity work.kick_sound_cpu
-port map(
- clk => clock_sndn,
- addr => cpu_addr(13 downto 0),
- data => cpu_rom_do
-);
+cpu_rom_addr <= cpu_addr(13 downto 0);
+cpu_rom_rd <= '1' when cpu_mreq_n = '0' and cpu_rd_n = '0' and cpu_addr(15 downto 14) = "00" else '0'; -- 0x0000-0x3FFF
+
+--rom_cpu : entity work.kick_sound_cpu
+--port map(
+-- clk => clock_sndn,
+-- addr => cpu_addr(13 downto 0),
+-- data => cpu_rom_do
+--);
-- working RAM 0x8000-0x83FF
wram : entity work.gen_ram
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/pll_mist.ppf b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/pll_mist.ppf
new file mode 100644
index 00000000..fc447489
--- /dev/null
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/pll_mist.ppf
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/sdram.sv b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/sdram.sv
index 8f927d05..24cfd9ee 100644
--- a/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/sdram.sv
+++ b/Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/sdram.sv
@@ -1,79 +1,126 @@
//
// sdram.v
//
-// Static RAM controller implementation using SDRAM MT48LC16M16A2
+// sdram controller implementation for the MiST board
+// https://github.com/mist-devel/mist-board
+//
+// Copyright (c) 2013 Till Harbaum
+// Copyright (c) 2019 Gyorgy Szombathelyi
//
-// Copyright (c) 2015,2016 Sorgelig
-//
-// Some parts of SDRAM code used from project:
-// http://hamsterworks.co.nz/mediawiki/index.php/Simple_SDRAM_Controller
-//
-// This source file is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published
-// by the Free Software Foundation, either version 3 of the License, or
+// This source file is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-//
-// ------------------------------------------
-//
-// v2.1 - Add universal 8/16 bit mode.
+// along with this program. If not, see .
//
-module sdram
-(
- input init, // reset to initialize RAM
- input clk, // clock ~100MHz
- //
- // SDRAM_* - signals to the MT48LC16M16 chip
- inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
- output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
- output reg SDRAM_DQML, // two byte masks
- output reg SDRAM_DQMH, //
- output reg [1:0] SDRAM_BA, // two banks
- output SDRAM_nCS, // a single chip select
- output SDRAM_nWE, // write enable
- output SDRAM_nRAS, // row address select
- output SDRAM_nCAS, // columns address select
- output SDRAM_CKE, // clock enable
- //
- input [1:0] wtbt, // 16bit mode: bit1 - write high byte, bit0 - write low byte,
- // 8bit mode: 2'b00 - use addr[0] to decide which byte to write
- // Ignored while reading.
- //
- input [24:0] addr, // 25 bit address for 8bit mode. addr[0] = 0 for 16bit mode for correct operations.
- output [15:0] dout, // data output to cpu
- input [15:0] din, // data input from cpu
- input we, // cpu requests write
- input rd, // cpu requests read
- output reg ready // dout is valid. Ready to accept new read/write.
+module sdram (
+
+ // interface to the MT48LC16M16 chip
+ inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus
+ output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus
+ output reg SDRAM_DQML, // two byte masks
+ output reg SDRAM_DQMH, // two byte masks
+ output reg [1:0] SDRAM_BA, // two banks
+ output SDRAM_nCS, // a single chip select
+ output SDRAM_nWE, // write enable
+ output SDRAM_nRAS, // row address select
+ output SDRAM_nCAS, // columns address select
+
+ // cpu/chipset interface
+ input init_n, // init signal after FPGA config to initialize RAM
+ input clk, // sdram clock
+
+ input port1_req,
+ output reg port1_ack,
+ input port1_we,
+ input [23:1] port1_a,
+ input [1:0] port1_ds,
+ input [15:0] port1_d,
+ output [15:0] port1_q,
+
+ input port2_req,
+ output reg port2_ack,
+ input port2_we,
+ input [23:1] port2_a,
+ input [1:0] port2_ds,
+ input [15:0] port2_d,
+ output [15:0] port2_q
);
-assign SDRAM_nCS = command[3];
-assign SDRAM_nRAS = command[2];
-assign SDRAM_nCAS = command[1];
-assign SDRAM_nWE = command[0];
-assign SDRAM_CKE = cke;
+localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz
+localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8
+localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
+localparam CAS_LATENCY = 3'd2; // 2/3 allowed
+localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
+localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
-// no burst configured
-localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8
-localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
-localparam CAS_LATENCY = 3'd2; // 2 for < 100MHz, 3 for >100MHz
-localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
-localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
-localparam MODE = {3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
+localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
-localparam sdram_startup_cycles= 14'd12100;// 100us, plus a little more, @ 100MHz
-localparam cycles_per_refresh = 14'd186; // (64000*36)/8192-1 Calc'd as (64ms @ 36MHz)/8192 rose
-localparam startup_refresh_max = 14'b11111111111111;
+// 64ms/8192 rows = 7.8us -> 842 cycles@108MHz
+localparam RFRSH_CYCLES = 10'd842;
-// SDRAM commands
+// ---------------------------------------------------------------------
+// ------------------------ cycle state machine ------------------------
+// ---------------------------------------------------------------------
+
+/*
+ SDRAM state machine for 2 bank interleaved access
+ 1 word burst, CL2
+cmd issued registered
+ 0 RAS0 cas1
+ 1 ras0
+ 2 CAS0 data1 returned
+ 3 RAS1 cas0
+ 4 ras1
+ 5 CAS1 data0 returned
+*/
+
+localparam STATE_RAS0 = 3'd0; // first state in cycle
+localparam STATE_RAS1 = 3'd3; // Second ACTIVE command after RAS0 + tRRD (15ns)
+localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY; // CAS phase - 3
+localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 5
+localparam STATE_READ0 = STATE_CAS0 + CAS_LATENCY + 1'd1; // 7
+localparam STATE_READ1 = 3'd2;
+localparam STATE_LAST = 3'd5;
+
+reg [2:0] t;
+
+always @(posedge clk) begin
+ t <= t + 1'd1;
+ if (t == STATE_LAST) t <= STATE_RAS0;
+end
+
+// ---------------------------------------------------------------------
+// --------------------------- startup/reset ---------------------------
+// ---------------------------------------------------------------------
+
+// wait 1ms (32 8Mhz cycles) after FPGA config is done before going
+// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
+reg [4:0] reset;
+reg init = 1'b1;
+always @(posedge clk, negedge init_n) begin
+ if(!init_n) begin
+ reset <= 5'h1f;
+ init <= 1'b1;
+ end else begin
+ if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1;
+ init <= !(reset == 0);
+ end
+end
+
+// ---------------------------------------------------------------------
+// ------------------ generate ram control signals ---------------------
+// ---------------------------------------------------------------------
+
+// all possible commands
localparam CMD_INHIBIT = 4'b1111;
localparam CMD_NOP = 4'b0111;
localparam CMD_ACTIVE = 4'b0011;
@@ -84,171 +131,149 @@ localparam CMD_PRECHARGE = 4'b0010;
localparam CMD_AUTO_REFRESH = 4'b0001;
localparam CMD_LOAD_MODE = 4'b0000;
-reg [13:0] refresh_count = startup_refresh_max - sdram_startup_cycles;
-reg [3:0] command = CMD_INHIBIT;
-reg cke = 0;
-reg [24:0] save_addr;
-reg [15:0] data;
+reg [3:0] sd_cmd; // current command sent to sd ram
-assign dout = save_addr[0] ? {data[7:0], data[15:8]} : {data[15:8], data[7:0]};
-typedef enum
-{
- STATE_STARTUP,
- STATE_OPEN_1,
- STATE_WRITE,
- STATE_READ,
- STATE_IDLE, STATE_IDLE_1, STATE_IDLE_2, STATE_IDLE_3,
- STATE_IDLE_4, STATE_IDLE_5, STATE_IDLE_6, STATE_IDLE_7
-} state_t;
+// drive control signals according to current command
+assign SDRAM_nCS = sd_cmd[3];
+assign SDRAM_nRAS = sd_cmd[2];
+assign SDRAM_nCAS = sd_cmd[1];
+assign SDRAM_nWE = sd_cmd[0];
-state_t state = STATE_STARTUP;
+reg [24:1] addr_latch[2];
+reg [24:1] addr_latch_next[2];
+reg [15:0] din_latch[2];
+reg [1:0] oe_latch;
+reg [1:0] we_latch;
+reg [1:0] ds[2];
+
+localparam PORT_NONE = 1'b0;
+localparam PORT_REQ = 1'b1;
+
+reg next_port[2];
+
+reg refresh;
+reg [10:0] refresh_cnt;
+wire need_refresh = (refresh_cnt >= RFRSH_CYCLES);
+
+// PORT1: bank 0,1
+always @(*) begin
+ if (port1_req ^ port1_ack) begin
+ next_port[0] = PORT_REQ;
+ addr_latch_next[0] = { 1'b0, port1_a };
+ end else begin
+ next_port[0] = PORT_NONE;
+ addr_latch_next[0] = addr_latch[0];
+ end
+end
+
+// PORT1: bank 2,3
+always @(*) begin
+ if ((port2_req ^ port2_ack) && !refresh) begin
+ next_port[1] = PORT_REQ;
+ addr_latch_next[1] = { 1'b1, port2_a };
+ end else begin
+ next_port[1] = PORT_NONE;
+ addr_latch_next[1] = addr_latch[1];
+ end
+end
always @(posedge clk) begin
- reg old_we, old_rd;
- reg [CAS_LATENCY:0] data_ready_delay;
- reg [15:0] new_data;
- reg [1:0] new_wtbt;
- reg new_we;
- reg new_rd;
- reg save_we = 1;
-
-
- command <= CMD_NOP;
- refresh_count <= refresh_count+1'b1;
-
- data_ready_delay <= {1'b0, data_ready_delay[CAS_LATENCY:1]};
-
- if(data_ready_delay[0]) data <= SDRAM_DQ;
-
- case(state)
- STATE_STARTUP: begin
- //------------------------------------------------------------------------
- //-- This is the initial startup state, where we wait for at least 100us
- //-- before starting the start sequence
- //--
- //-- The initialisation is sequence is
- //-- * de-assert SDRAM_CKE
- //-- * 100us wait,
- //-- * assert SDRAM_CKE
- //-- * wait at least one cycle,
- //-- * PRECHARGE
- //-- * wait 2 cycles
- //-- * REFRESH,
- //-- * tREF wait
- //-- * REFRESH,
- //-- * tREF wait
- //-- * LOAD_MODE_REG
- //-- * 2 cycles wait
- //------------------------------------------------------------------------
- cke <= 1;
- SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
- SDRAM_DQML <= 1;
- SDRAM_DQMH <= 1;
- SDRAM_A <= 0;
- SDRAM_BA <= 0;
-
- // All the commands during the startup are NOPS, except these
- if(refresh_count == startup_refresh_max-31) begin
- // ensure all rows are closed
- command <= CMD_PRECHARGE;
- SDRAM_A[10] <= 1; // all banks
- SDRAM_BA <= 2'b00;
- end else if (refresh_count == startup_refresh_max-23) begin
- // these refreshes need to be at least tREF (66ns) apart
- command <= CMD_AUTO_REFRESH;
- end else if (refresh_count == startup_refresh_max-15)
- command <= CMD_AUTO_REFRESH;
- else if (refresh_count == startup_refresh_max-7) begin
- // Now load the mode register
- command <= CMD_LOAD_MODE;
- SDRAM_A <= MODE;
- end
-
- //------------------------------------------------------
- //-- if startup is complete then go into idle mode,
- //-- get prepared to accept a new command, and schedule
- //-- the first refresh cycle
- //------------------------------------------------------
- if(!refresh_count) begin
- state <= STATE_IDLE;
- ready <= 1;
- refresh_count <= 0;
- end
- end
-
- STATE_IDLE_7: state <= STATE_IDLE_6;
- STATE_IDLE_6: state <= STATE_IDLE_5;
- STATE_IDLE_5: state <= STATE_IDLE_4;
- STATE_IDLE_4: state <= STATE_IDLE_3;
- STATE_IDLE_3: state <= STATE_IDLE_2;
- STATE_IDLE_2: state <= STATE_IDLE_1;
- STATE_IDLE_1: begin
- SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
- state <= STATE_IDLE;
- // mask possible refresh to reduce colliding.
- if(refresh_count > cycles_per_refresh) begin
- //------------------------------------------------------------------------
- //-- Start the refresh cycle.
- //-- This tasks tRFC (66ns), so 2 idle cycles are needed @ 36MHz
- //------------------------------------------------------------------------
- state <= STATE_IDLE_2;
- command <= CMD_AUTO_REFRESH;
- refresh_count <= refresh_count - cycles_per_refresh + 1'd1;
- end
- end
-
- STATE_IDLE: begin
- // Priority is to issue a refresh if one is outstanding
- if(refresh_count > (cycles_per_refresh<<1)) state <= STATE_IDLE_1;
- else if(new_rd | new_we) begin
- new_we <= 0;
- new_rd <= 0;
- save_addr<= addr;
- save_we <= new_we;
- state <= STATE_OPEN_1;
- command <= CMD_ACTIVE;
- SDRAM_A <= addr[13:1];
- SDRAM_BA <= addr[24:23];
- end
- end
-
- // ACTIVE-to-READ or WRITE delay >20ns (1 cycle @ 36 MHz)(-75)
- STATE_OPEN_1: begin
- SDRAM_A <= {4'b0010, save_addr[22:14]};
- SDRAM_DQML <= save_we & (new_wtbt ? ~new_wtbt[0] : save_addr[0]);
- SDRAM_DQMH <= save_we & (new_wtbt ? ~new_wtbt[1] : ~save_addr[0]);
- state <= save_we ? STATE_WRITE : STATE_READ;
- end
-
- STATE_READ: begin
- state <= STATE_IDLE_5;
- command <= CMD_READ;
- SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
-
- // Schedule reading the data values off the bus
- data_ready_delay[CAS_LATENCY] <= 1;
- end
-
- STATE_WRITE: begin
- state <= STATE_IDLE_5;
- command <= CMD_WRITE;
- SDRAM_DQ <= new_wtbt ? new_data : {new_data[7:0], new_data[7:0]};
- ready <= 1;
- end
- endcase
+ // permanently latch ram data to reduce delays
+ SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ;
+ { SDRAM_DQMH, SDRAM_DQML } <= 2'b11;
+ sd_cmd <= CMD_NOP; // default: idle
+ refresh_cnt <= refresh_cnt + 1'd1;
if(init) begin
- state <= STATE_STARTUP;
- refresh_count <= startup_refresh_max - sdram_startup_cycles;
+ // initialization takes place at the end of the reset phase
+ if(t == STATE_RAS0) begin
+
+ if(reset == 15) begin
+ sd_cmd <= CMD_PRECHARGE;
+ SDRAM_A[10] <= 1'b1; // precharge all banks
+ end
+
+ if(reset == 10 || reset == 8) begin
+ sd_cmd <= CMD_AUTO_REFRESH;
+ end
+
+ if(reset == 2) begin
+ sd_cmd <= CMD_LOAD_MODE;
+ SDRAM_A <= MODE;
+ SDRAM_BA <= 2'b00;
+ end
+ end
+ end else begin
+ // RAS phase
+ // bank 0,1
+ if(t == STATE_RAS0) begin
+ addr_latch[0] <= addr_latch_next[0];
+ { oe_latch[0], we_latch[0] } <= 2'b00;
+ if (next_port[0] != PORT_NONE) begin
+ sd_cmd <= CMD_ACTIVE;
+ SDRAM_A <= addr_latch_next[0][22:10];
+ SDRAM_BA <= addr_latch_next[0][24:23];
+ { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we };
+ ds[0] <= port1_ds;
+ din_latch[0] <= port1_d;
+ end
+ end
+
+ // bank 2,3
+ if(t == STATE_RAS1) begin
+ refresh <= 1'b0;
+ addr_latch[1] <= addr_latch_next[1];
+ { oe_latch[1], we_latch[1] } <= 2'b00;
+ if (next_port[1] != PORT_NONE) begin
+ sd_cmd <= CMD_ACTIVE;
+ SDRAM_A <= addr_latch_next[1][22:10];
+ SDRAM_BA <= addr_latch_next[1][24:23];
+ { oe_latch[1], we_latch[1] } <= { ~port1_we, port1_we };
+ ds[1] <= port2_ds;
+ din_latch[1] <= port2_d;
+ end
+
+ if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin
+ refresh <= 1'b1;
+ refresh_cnt <= 0;
+ sd_cmd <= CMD_AUTO_REFRESH;
+ end
+ end
+
+ // CAS phase
+ if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin
+ sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ;
+ { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0];
+ if (we_latch[0]) begin
+ SDRAM_DQ <= din_latch[0];
+ port1_ack <= port1_req;
+ end
+ SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge
+ SDRAM_BA <= addr_latch[0][24:23];
+ end
+
+ if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin
+ sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ;
+ { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1];
+ if (we_latch[1]) begin
+ SDRAM_DQ <= din_latch[1];
+ port2_ack <= port2_req;
+ end
+ SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge
+ SDRAM_BA <= addr_latch[1][24:23];
+ end
+
+ // Data returned
+ if(t == STATE_READ0 && oe_latch[0]) begin
+ port1_q <= SDRAM_DQ;
+ port1_ack <= port1_req;
+ end
+ if(t == STATE_READ1 && oe_latch[1]) begin
+ port2_q <= SDRAM_DQ;
+ port2_ack <= port2_req;
+ end
end
-
- old_we <= we;
- old_rd <= rd;
- if(we & ~old_we) {ready, new_we, new_data, new_wtbt} <= {1'b0, 1'b1, din, wtbt};
- else
- if((rd & ~old_rd) || (rd & old_rd & (save_addr != addr))) {ready, new_rd} <= {1'b0, 1'b1};
-
end
endmodule