From fd0ecf2c7c688af256065ca48c872df1c411a8b0 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Thu, 7 Nov 2019 21:38:44 +0100 Subject: [PATCH] Kickman: new dual-port SDRAM controller, load sound ROM to SDRAM --- .../Midway MCR 1/Kickman_MiST/Kickman.sdc | 7 +- .../Midway MCR 1/Kickman_MiST/README.txt | 4 + .../Kickman_MiST/Release/KICKMAN.ROM | Bin 24576 -> 40960 bytes .../Kickman_MiST/rtl/Kickman_MiST.sv | 68 ++- .../Midway MCR 1/Kickman_MiST/rtl/kick.vhd | 12 +- .../Kickman_MiST/rtl/kick_sound_board.vhd | 23 +- .../Kickman_MiST/rtl/pll_mist.ppf | 11 + .../Midway MCR 1/Kickman_MiST/rtl/sdram.sv | 457 +++++++++--------- 8 files changed, 339 insertions(+), 243 deletions(-) create mode 100644 Arcade_MiST/Midway MCR 1/Kickman_MiST/rtl/pll_mist.ppf 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 8fc0d5fe8f77082fc47217c633755cc0d9da2b86..9ecbd5b6c2160ad71488b7fde6698646db618115 100644 GIT binary patch delta 16482 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 delta 8 PcmZoTz|?SnaX|tA5O)KF 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