Files
vhdl/lib/SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd
T
jens 4646c2ef34 - simplified PHY control signals
- revert apparent BURST fix

git-svn-id: http://moon:8086/svn/vhdl/trunk@1260 cc03376c-175c-47c8-b038-4cd826a8556b
2015-05-30 08:31:08 +00:00

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;