- revert apparent BURST fix git-svn-id: http://moon:8086/svn/vhdl/trunk@1260 cc03376c-175c-47c8-b038-4cd826a8556b
260 lines
6.7 KiB
VHDL
260 lines
6.7 KiB
VHDL
-------------------------------------------------------------------------
|
|
-- Project: SDRAM controller
|
|
-- This file: SDRAM command controller
|
|
--
|
|
-- Copyright (C) 2007 J. Ahrensfeld
|
|
--
|
|
-- This program 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 program 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 <http://www.gnu.org/licenses/>.
|
|
--
|
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
--
|
|
--------------------------------------------------------------------------
|
|
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.numeric_std.ALL;
|
|
|
|
use work.sdram_const.all;
|
|
use work.sdram_config.all;
|
|
use work.sdram_types.all;
|
|
|
|
entity sdram_cmd is
|
|
Generic
|
|
(
|
|
F_SDRCLK : real := 100.0
|
|
);
|
|
Port
|
|
(
|
|
rst : in STD_LOGIC;
|
|
clk : in STD_LOGIC;
|
|
tag : in user_tag_t;
|
|
col_addr : in col_addr_t;
|
|
mode_word : in mode_word_t;
|
|
cmd : in sdr_cmd_t;
|
|
cmd_we : in STD_LOGIC;
|
|
cmd_ack : out STD_LOGIC;
|
|
phy_ctrl : out phy_ctrl_t
|
|
);
|
|
end sdram_cmd;
|
|
|
|
architecture behaviour of sdram_cmd is
|
|
|
|
subtype cycle_cnt_t is natural range 0 to 15;
|
|
subtype burst_cnt_t is natural range 0 to 2**(LMR_BL_CURR)-1;
|
|
|
|
signal cc_load_en : std_logic;
|
|
signal cycle_finished : std_logic;
|
|
signal cycle_cnt : cycle_cnt_t;
|
|
|
|
signal burst_finished : std_logic;
|
|
signal burst_cnt : burst_cnt_t;
|
|
|
|
signal st_sdr, st_sdr_next : sdr_state_t;
|
|
|
|
type part_timing_array_t is array (sdr_cmd_t) of cycle_cnt_t;
|
|
constant TIMING : part_timing_array_t :=
|
|
-- command cycle_cnt
|
|
( SD_DESELECT => (0 ),
|
|
SD_NOP => (0 ),
|
|
SD_LMR => (TMRD-1 ),
|
|
SD_ACT => (to_cycles(TRCD, F_SDRCLK)-1),
|
|
SD_READ => (TCAS-1 ),
|
|
SD_WRITE => (to_cycles(TWR, F_SDRCLK)-1),
|
|
SD_PRE => (to_cycles(TRP, F_SDRCLK)-1),
|
|
SD_BST => (0 ),
|
|
SD_AR => (to_cycles(TRFC, F_SDRCLK)-1),
|
|
SD_SR => (to_cycles(TRFC, F_SDRCLK)-1)
|
|
);
|
|
|
|
begin
|
|
|
|
------------------------------------------------------------------------------------------
|
|
|
|
fsm_sdr_state:
|
|
process (st_sdr, cmd, cmd_we, cycle_finished, burst_finished, mode_word, col_addr, tag)
|
|
begin
|
|
st_sdr_next <= st_sdr;
|
|
phy_ctrl.part.cmd <= COMMAND(SD_NOP);
|
|
phy_ctrl.part.cke <= '1';
|
|
phy_ctrl.u_tag <= tag;
|
|
cc_load_en <= '0';
|
|
cmd_ack <= '0';
|
|
phy_ctrl.re <= '0';
|
|
phy_ctrl.we <= '0';
|
|
phy_ctrl.utag_we <= '0';
|
|
phy_ctrl.part.addr <= mode_word(phy_ctrl.part.addr'left downto phy_ctrl.part.addr'right);
|
|
phy_ctrl.part.ba <= mode_word(mode_word_t'left downto mode_word_t'left-1);
|
|
|
|
case st_sdr is
|
|
|
|
when PWR_DOWN =>
|
|
phy_ctrl.part.cke <= '0';
|
|
phy_ctrl.part.cmd <= COMMAND(SD_DESELECT);
|
|
if cmd_we = '1' then
|
|
cmd_ack <= '1';
|
|
cc_load_en <= '1';
|
|
if cmd = SD_NOP then
|
|
st_sdr_next <= IDLE_WAIT;
|
|
end if;
|
|
end if;
|
|
|
|
when IDLE_WAIT =>
|
|
if cycle_finished = '1' then
|
|
st_sdr_next <= IDLE;
|
|
end if;
|
|
|
|
when IDLE =>
|
|
if cmd_we = '1' then
|
|
cmd_ack <= '1';
|
|
cc_load_en <= '1';
|
|
phy_ctrl.part.cmd <= COMMAND(cmd);
|
|
case cmd is
|
|
when SD_PRE =>
|
|
st_sdr_next <= PRECHARGE;
|
|
when SD_LMR =>
|
|
st_sdr_next <= MODE;
|
|
when SD_ACT =>
|
|
st_sdr_next <= ROW_ACT;
|
|
when SD_AR =>
|
|
st_sdr_next <= AUTO_REF;
|
|
when SD_READ =>
|
|
phy_ctrl.utag_we <= '1';
|
|
st_sdr_next <= READ;
|
|
phy_ctrl.part.addr(col_addr_t'range) <= col_addr;
|
|
when SD_WRITE =>
|
|
phy_ctrl.utag_we <= '1';
|
|
phy_ctrl.we <= '1';
|
|
st_sdr_next <= WRITE;
|
|
phy_ctrl.part.addr(col_addr_t'range) <= col_addr;
|
|
when others => null;
|
|
end case;
|
|
end if;
|
|
|
|
when WRITE =>
|
|
phy_ctrl.we <= '1';
|
|
phy_ctrl.part.cmd <= COMMAND(SD_NOP);
|
|
phy_ctrl.part.addr(col_addr_t'range) <= col_addr;
|
|
if burst_finished = '1' then
|
|
if cmd_we = '1' and cmd = SD_WRITE then
|
|
cmd_ack <= '1';
|
|
cc_load_en <= '1';
|
|
phy_ctrl.part.cmd <= COMMAND(cmd);
|
|
phy_ctrl.utag_we <= '1';
|
|
else
|
|
phy_ctrl.we <= '0';
|
|
st_sdr_next <= IDLE_WAIT;
|
|
end if;
|
|
end if;
|
|
|
|
when READ =>
|
|
phy_ctrl.re <= '1';
|
|
phy_ctrl.part.cmd <= COMMAND(SD_NOP);
|
|
phy_ctrl.part.addr(col_addr_t'range) <= col_addr;
|
|
if burst_finished = '1' then
|
|
if cmd_we = '1' and cmd = SD_READ then
|
|
cmd_ack <= '1';
|
|
cc_load_en <= '1';
|
|
phy_ctrl.part.cmd <= COMMAND(cmd);
|
|
phy_ctrl.utag_we <= '1';
|
|
else
|
|
st_sdr_next <= IDLE_WAIT;
|
|
end if;
|
|
end if;
|
|
|
|
when PRECHARGE =>
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when MODE =>
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when ROW_ACT =>
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when WRITE_A => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when READ_A => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when BURST_STOP => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when SELF_REF => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when PRE_PWR_DOWN => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when ACT_PWR_DOWN => -- not implemented yet
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when AUTO_REF =>
|
|
st_sdr_next <= IDLE_WAIT;
|
|
|
|
when others =>
|
|
st_sdr_next <= IDLE;
|
|
end case;
|
|
|
|
end process;
|
|
|
|
fsm_sdr_state_next:
|
|
process (clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if rst = '1' then
|
|
st_sdr <= PWR_DOWN;
|
|
else
|
|
st_sdr <= st_sdr_next;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------------------------------
|
|
cycle_counter:
|
|
process (clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if cc_load_en = '1' then
|
|
cycle_finished <= '0';
|
|
cycle_cnt <= TIMING(cmd);
|
|
elsif cycle_cnt /= 0 then
|
|
cycle_cnt <= cycle_cnt - 1;
|
|
else
|
|
cycle_finished <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------------------------------
|
|
burst_counter:
|
|
process (clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if cc_load_en = '1' then
|
|
burst_finished <= '0';
|
|
burst_cnt <= burst_cnt_t'high;
|
|
if 2**(LMR_BL_CURR) = DATA_RATE_FACTOR then
|
|
burst_finished <= '1';
|
|
end if;
|
|
elsif burst_cnt <= DATA_RATE_FACTOR then
|
|
burst_finished <= '1';
|
|
else
|
|
burst_cnt <= burst_cnt - DATA_RATE_FACTOR;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
------------------------------------------------------------------------------------------
|
|
end behaviour;
|