Project

General

Profile

---------------------------------------------------------------------------
-- (c) 2013 mark watson
-- I am happy for anyone to use this for non-commercial use.
-- If my vhdl files are used commercially or otherwise sold,
-- please contact me for explicit permission at scrameta (gmail).
-- This applies for source and binary form and derived works.
---------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;

ENTITY sdram_statemachine_mcc IS
generic
(
ADDRESS_WIDTH : natural := 22;
ROW_WIDTH : natural := 12;
AP_BIT : natural := 10;
COLUMN_WIDTH : natural := 8
);
PORT
(
CLK_SYSTEM : IN STD_LOGIC;
CLK_SDRAM : IN STD_LOGIC; -- this is a exact multiple of system clock
RESET_N : in STD_LOGIC;
-- interface as though SRAM - this module can take care of caching/write combining etc etc. For first cut... nothing. TODO: What extra info would help me here?
DATA_IN : in std_logic_vector(31 downto 0);
ADDRESS_IN : in std_logic_vector(ADDRESS_WIDTH downto 0); -- 1 extra bit for byte alignment
READ_EN : in std_logic; -- if no reads pending may be a good time to do a refresh
WRITE_EN : in std_logic;
REQUEST : in std_logic; -- Toggle this to issue a new request
BYTE_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0111, if 1=1011. Data fields valid:7 downto 0.
WORD_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0011, if 1=1001. Data fields valid:15 downto 0.
LONGWORD_ACCESS : in std_logic; -- a(0) ignored. lqdm/udqm mask is 0000
REFRESH : in std_logic;

REPLY : out std_logic; -- This matches the request once complete
DATA_OUT : out std_logic_vector(31 downto 0);

-- sdram itself
SDRAM_ADDR : out std_logic_vector(ROW_WIDTH downto 0);
SDRAM_DQ : inout std_logic_vector(15 downto 0);
SDRAM_BA0 : out std_logic;
SDRAM_BA1 : out std_logic;
SDRAM_CS_N : out std_logic;
SDRAM_RAS_N : out std_logic;
SDRAM_CAS_N : out std_logic;
SDRAM_WE_N : out std_logic;
SDRAM_ldqm : out std_logic; -- low enable, high disable - for byte addressing - NB, cas latency applies to reads
SDRAM_udqm : out std_logic
);
END sdram_statemachine_mcc;

ARCHITECTURE vhdl OF sdram_statemachine_mcc IS
component sdram_ctrl
port
(
-- //-----------------------------
-- // Clock and reset
-- //-----------------------------
-- input rst, // Global reset
-- input clk, // Master clock (72 MHz)
--
-- output ram_rdy_n, // SDRAM ready
-- output ram_ref, // SDRAM refresh
-- output [3:0] ram_cyc, // SDRAM cycles
-- output [3:0] ram_ph, // SDRAM phases
-- output [8:0] ram_ph_ctr, // Phase counter
rst : in std_logic;
clk : in std_logic;
ram_rdy_n : out std_logic;
ram_ref : out std_logic;
ram_cyc : out std_logic_vector(3 downto 0);
ram_ph : out std_logic_vector(3 downto 0);
ram_ph_ctr : out std_logic_vector(8 downto 0);
rden_b0 : in std_logic;
wren_b0 : in std_logic;
addr_b0 : in std_logic_vector(22 downto 2);
valid_b0 : out std_logic;
fetch_b0 : out std_logic;
rdata_b0 : out std_logic_vector(15 downto 0);
wdata_b0 : in std_logic_vector(15 downto 0);
bena_b0 : in std_logic_vector(1 downto 0);

rden_b1 : in std_logic;
wren_b1 : in std_logic;
addr_b1 : in std_logic_vector(22 downto 2);
valid_b1 : out std_logic;
fetch_b1 : out std_logic;
rdata_b1 : out std_logic_vector(15 downto 0);
wdata_b1 : in std_logic_vector(15 downto 0);
bena_b1 : in std_logic_vector(1 downto 0);

rden_b2 : in std_logic;
wren_b2 : in std_logic;
addr_b2 : in std_logic_vector(22 downto 2);
valid_b2 : out std_logic;
fetch_b2 : out std_logic;
rdata_b2 : out std_logic_vector(15 downto 0);
wdata_b2 : in std_logic_vector(15 downto 0);
bena_b2 : in std_logic_vector(1 downto 0);

rden_b3 : in std_logic;
wren_b3 : in std_logic;
addr_b3 : in std_logic_vector(22 downto 2);
valid_b3 : out std_logic;
fetch_b3 : out std_logic;
rdata_b3 : out std_logic_vector(15 downto 0);
wdata_b3 : in std_logic_vector(15 downto 0);
bena_b3 : in std_logic_vector(1 downto 0);
-- //-----------------------------
-- // Access bank #0
-- //-----------------------------
-- input rden_b0, // Read enable
-- input wren_b0, // Write enable
-- input [22:2] addr_b0, // Address (up to 8 MB)
-- output valid_b0, // Read data valid
-- output fetch_b0, // Write data fetch
-- output [15:0] rdata_b0, // Read data
-- input [15:0] wdata_b0, // Write data
-- input [1:0] bena_b0, // Byte enable
--
-- //-----------------------------
-- // Access bank #1
-- //-----------------------------
-- input rden_b1, // Read enable
-- input wren_b1, // Write enable
-- input [22:2] addr_b1, // Address (up to 8 MB)
-- output valid_b1, // Read data valid
-- output fetch_b1, // Write data fetch
-- output [15:0] rdata_b1, // Read data
-- input [15:0] wdata_b1, // Write data
-- input [1:0] bena_b1, // Byte enable
--
-- //-----------------------------
-- // Access bank #2
-- //-----------------------------
-- input rden_b2, // Read enable
-- input wren_b2, // Write enable
-- input [22:2] addr_b2, // Address (up to 8 MB)
-- output valid_b2, // Read data valid
-- output fetch_b2, // Write data fetch
-- output [15:0] rdata_b2, // Read data
-- input [15:0] wdata_b2, // Write data
-- input [1:0] bena_b2, // Byte enable
--
-- //-----------------------------
-- // Access bank #3
-- //-----------------------------
-- input rden_b3, // Read enable
-- input wren_b3, // Write enable
-- input [22:2] addr_b3, // Address (up to 8 MB)
-- output valid_b3, // Read data valid
-- output fetch_b3, // Write data fetch
-- output [15:0] rdata_b3, // Read data
-- input [15:0] wdata_b3, // Write data
-- input [1:0] bena_b3, // Byte enable
-- //-----------------------------
-- // SDRAM memory signals
-- //-----------------------------
-- output sdram_cs_n, // SDRAM chip select
-- output reg sdram_ras_n, // SDRAM row address strobe
-- output reg sdram_cas_n, // SDRAM column address strobe
-- output reg sdram_we_n, // SDRAM write enable
-- //
-- output reg [1:0] sdram_ba, // SDRAM bank address
-- output reg [12:0] sdram_addr, // SDRAM address
-- //
-- output reg [3:0] sdram_dqm_n, // SDRAM DQ masks
-- output reg sdram_dq_oe, // SDRAM data output enable
-- output reg [31:0] sdram_dq_o, // SDRAM data output
-- input [31:0] sdram_dq_i // SDRAM data input

sdram_cs_n : out std_logic;
sdram_ras_n : out std_logic;
sdram_cas_n : out std_logic;
sdram_we_n : out std_logic;
sdram_ba : out std_logic_vector(1 downto 0);
sdram_addr : out std_logic_vector(12 downto 0);
sdram_dqm_n : out std_logic_vector(3 downto 0);
sdram_dq_oe : out std_logic;
sdram_dq_o : out std_logic_vector(31 downto 0);
sdram_dq_i : in std_logic_vector(31 downto 0)
);
end component;

signal SDRAM_CKE_dummy : std_logic;

signal sdram_valid_b0_dummy : std_logic;
signal sdram_valid_b1_dummy : std_logic;
signal sdram_valid_b2_dummy : std_logic;
signal sdram_valid_b3_dummy : std_logic;

signal sdram_fetch_b0_dummy : std_logic;
signal sdram_fetch_b1_dummy : std_logic;
signal sdram_fetch_b2_dummy : std_logic;
signal sdram_fetch_b3_dummy : std_logic;

signal sdram_read_b0_dummy : std_logic_vector(15 downto 0);
signal sdram_read_b1_dummy : std_logic_vector(15 downto 0);
signal sdram_read_b2_dummy : std_logic_vector(15 downto 0);
signal sdram_read_b3_dummy : std_logic_vector(15 downto 0);

signal reset : std_logic;

signal sdram_ctl_rdy_dummy : std_logic;
signal sdram_ctl_ref_dummy : std_logic;
signal sdram_ctl_cyc_dummy : std_logic_vector(3 downto 0);
signal sdram_ctl_ph_dummy : std_logic_vector(3 downto 0);
signal sdram_ctl_ph_ctr_dummy : std_logic_vector(8 downto 0);

signal SDRAM_VALID : std_logic;
signal SDRAM_FETCH : std_logic;

signal SDRAM_dq_oe : std_logic;
signal sdram_dq_o : std_logic_vector(31 downto 0);
signal sdram_dq_i : std_logic_vector(31 downto 0);
signal sdram_dqm_N_temp : std_logic_vector(3 downto 0);

signal sdram_ba : std_logic_vector(1 downto 0);

signal sdram_enable_byte : std_logic_vector(1 downto 0);

signal sdram_reply_reg : std_logic;
signal state_reg : std_logic_vector(2 downto 0);
signal store_data_in_reg : std_logic_vector(47 downto 0);
signal data_out_reg : std_logic_vector(31 downto 0);
signal sdram_reply_next : std_logic;
signal state_next : std_logic_vector(2 downto 0);
signal store_data_in_next : std_logic_vector(47 downto 0);
signal data_out_next : std_logic_vector(31 downto 0);

constant state_idle : std_logic_vector(2 downto 0) := "000";
constant state_write_wait_1 : std_logic_vector(2 downto 0) := "001";
constant state_write_wait_2 : std_logic_vector(2 downto 0) := "010";
constant state_write_wait_3 : std_logic_vector(2 downto 0) := "111";
constant state_read_wait_1 : std_logic_vector(2 downto 0) := "011";
constant state_read_wait_2 : std_logic_vector(2 downto 0) := "100";
constant state_read_wait_3 : std_logic_vector(2 downto 0) := "101";
constant state_read_wait_4 : std_logic_vector(2 downto 0) := "110";


signal internal_data_in : std_logic_vector(15 downto 0);
signal internal_data_out : std_logic_vector(15 downto 0);

signal write_en_next : std_logic;
signal write_en_reg : std_logic;

signal read_en_next : std_logic;
signal read_en_reg : std_logic;

signal SDRAM_ADDR_temp : std_logic_vector(12 downto 0);

begin


reset <= not(reset_n);

process(clk_system, reset_n)
begin
if (reset_n = '0') then
sdram_reply_reg <= '0';
state_reg <= state_idle;
store_data_in_reg <= (others=>'0');
data_out_reg <= (others=>'0');
write_en_reg <= '0';
read_en_reg <= '0';
elsif (clk_system'event and clk_system = '1') then
sdram_reply_reg <= sdram_reply_next;
state_reg <= state_next;
store_data_in_reg <= store_data_in_next;
data_out_reg <= data_out_next;
write_en_reg <= write_en_next;
read_en_reg <= read_en_next;
end if;
end process;

data_out <= data_out_reg;
reply <= sdram_reply_reg;

process(read_en_reg, write_en_reg, state_reg, request, write_en, store_data_in_reg, internal_data_in, data_in, sdram_reply_reg, byte_access, longword_access, address_in, sdram_valid, sdram_fetch)
begin
sdram_reply_next <= sdram_reply_reg;
state_next <= state_reg;
store_data_in_next <= store_data_in_reg;
data_out_next <= (others=>'0');
read_en_next <= read_en_reg;
write_en_next <= write_en_reg;
internal_data_out <= (others=>'0');
sdram_enable_byte <= "11";

case state_reg is
when state_idle =>
sdram_reply_next <= '0';
if (request = '1') then
if (write_en = '1') then
-- 4 byte write
state_next <= state_write_wait_1;
write_en_next <= '1';
else
-- 8 byte read
state_next <= state_read_wait_1;
read_en_next <= '1';
-- TODO - read from cached?
end if;
end if;
when state_write_wait_1 =>
if (sdram_fetch = '1') then
state_next <= state_write_wait_2;
end if;
internal_data_out <= data_in(31 downto 16);
when state_write_wait_2 =>
state_next <= state_write_wait_3;
if (byte_access = '1') then
internal_data_out <= data_in(7 downto 0)&data_in(7 downto 0);
case address_in(1 downto 0) is
when "00" =>
sdram_enable_byte <= "01";
when "01" =>
sdram_enable_byte <= "10";
when "10" =>
sdram_enable_byte <= "00";
when "11" =>
sdram_enable_byte <= "00";
end case;
elsif (longword_access = '1') then
internal_data_out <= data_in(15 downto 0);
end if;
sdram_reply_next <= '1';
when state_write_wait_3 =>
state_next <= state_idle;
write_en_next <= '0';
if (byte_access = '1') then
internal_data_out <= data_in(7 downto 0)&data_in(7 downto 0);
case address_in(1 downto 0) is
when "00" =>
sdram_enable_byte <= "00";
when "01" =>
sdram_enable_byte <= "00";
when "10" =>
sdram_enable_byte <= "01";
when "11" =>
sdram_enable_byte <= "10";
end case;
elsif (longword_access = '1') then
internal_data_out <= data_in(31 downto 16);
end if;
sdram_reply_next <= '0';
when state_read_wait_1 =>
if (sdram_valid = '1') then
state_next <= state_read_wait_2;
store_data_in_next(15 downto 0) <= internal_data_in;
end if;
when state_read_wait_2 =>
state_next <= state_read_wait_3;
store_data_in_next(31 downto 16) <= internal_data_in;
when state_read_wait_3 =>
state_next <= state_read_wait_4;
store_data_in_next(47 downto 32) <= internal_data_in;
when state_read_wait_4 =>
read_en_next <= '0';
state_next <= state_idle;
--store_data_in_next(63 downto 48) <= internal_data_in;
sdram_reply_next <= '1';
if (byte_access = '1') then
case address_in(2 downto 0) is
when "000" =>
data_out_next(7 downto 0) <= store_data_in_reg(7 downto 0);
when "001" =>
data_out_next(7 downto 0) <= store_data_in_reg(15 downto 8);
when "010" =>
data_out_next(7 downto 0) <= store_data_in_reg(23 downto 16);
when "011" =>
data_out_next(7 downto 0) <= store_data_in_reg(31 downto 24);
when "100" =>
data_out_next(7 downto 0) <= store_data_in_reg(39 downto 32);
when "101" =>
data_out_next(7 downto 0) <= store_data_in_reg(47 downto 40);
when "110" =>
data_out_next(7 downto 0) <= internal_data_in(7 downto 0);
when "111" =>
data_out_next(7 downto 0) <= internal_data_in(15 downto 8);
end case;
elsif (longword_access = '1') then
case address_in(2 downto 0) is -- aligned only!
when "000" =>
data_out_next <= store_data_in_reg(31 downto 0);
when "100" =>
data_out_next <= internal_data_in&store_data_in_reg(47 downto 32);
when others =>
-- NOP
end case;
end if;
end case;
end process;


sdram_mcc : sdram_ctrl
PORT map
(
rst => reset,
clk => clk_SYSTEM,
ram_rdy_n => sdram_ctl_rdy_dummy,
ram_ref => sdram_ctl_ref_dummy,
ram_cyc => sdram_ctl_cyc_dummy,
ram_ph => sdram_ctl_ph_dummy,
ram_ph_ctr => sdram_ctl_ph_ctr_dummy,

--BYTE_ACCESS : IN STD_LOGIC;
--WORD_ACCESS : IN STD_LOGIC;
--LONGWORD_ACCESS : IN STD_LOGIC;
rden_b0 => READ_EN_reg,
wren_b0 => WRITE_EN_reg,
addr_b0 => ADDRESS_IN(22 downto 2),
valid_b0 => SDRAM_VALID,
fetch_b0 => SDRAM_FETCH,
rdata_b0 => INTERNAL_DATA_IN(15 downto 0),
wdata_b0 => INTERNAL_DATA_OUT(15 downto 0),
bena_b0 => sdram_enable_byte,

rden_b1 => '0',
wren_b1 => '0',
addr_b1 => (others=>'0'),
valid_b1 => sdram_valid_b1_dummy,
fetch_b1 => sdram_fetch_b1_dummy,
rdata_b1 => sdram_read_b1_dummy,
wdata_b1 => (others=>'0'),
bena_b1 => "00",

rden_b2 => '0',
wren_b2 => '0',
addr_b2 => (others=>'0'),
valid_b2 => sdram_valid_b2_dummy,
fetch_b2 => sdram_fetch_b2_dummy,
rdata_b2 => sdram_read_b2_dummy,
wdata_b2 => (others=>'0'),
bena_b2 => "00",

rden_b3 => '0',
wren_b3 => '0',
addr_b3 => (others=>'0'),
valid_b3 => sdram_valid_b3_dummy,
fetch_b3 => sdram_fetch_b3_dummy,
rdata_b3 => sdram_read_b3_dummy,
wdata_b3 => (others=>'0'),
bena_b3 => "00",
sdram_cs_n => SDRAM_CS_N,
sdram_ras_n => SDRAM_RAS_N,
sdram_cas_n => SDRAM_CAS_N,
sdram_we_n => SDRAM_WE_N,
sdram_ba => SDRAM_BA,
sdram_addr => SDRAM_ADDR_temp,
sdram_dqm_n => sdram_dqm_N_temp,
sdram_dq_oe => sdram_dq_oe,
sdram_dq_o => sdram_dq_o,
sdram_dq_i => sdram_dq_i
);
sdram_dq <= sdram_dq_o(15 downto 0) when sdram_dq_oe='1' else (others=>'Z');
sdram_dq_i(15 downto 0) <= sdram_dq;
sdram_dq_i(31 downto 16) <= (others=>'0');
SDRAM_LDQM<= sdram_dqm_N_temp(0);
SDRAM_UDQM<= sdram_dqm_N_temp(1);
SDRAM_BA0 <= sdram_ba(0);
SDRAM_BA1 <= sdram_ba(1);

SDRAM_ADDR(12) <= '1';
SDRAM_ADDR(11 downto 0) <= SDRAM_ADDR_temp(11 downto 0);

end vhdl;
(32-32/44)