📄 sm.vhd
字号:
-- --------------------------------------------------------------------
-- >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
-- --------------------------------------------------------------------
-- Copyright (c) 2001 by Lattice Semiconductor Corporation
-- --------------------------------------------------------------------
--
-- Permission:
--
-- Lattice Semiconductor grants permission to use this code for use
-- in synthesis for any Lattice programmable logic product. Other
-- use of this code, including the selling or duplication of any
-- portion is strictly prohibited.
--
-- Disclaimer:
--
-- This VHDL or Verilog source code is intended as a design reference
-- which illustrates how these types of functions can be implemented.
-- It is the user's responsibility to verify their design for
-- consistency and functionality through the use of formal
-- verification methods. Lattice Semiconductor provides no warranty
-- regarding the use or functionality of this code.
--
-- --------------------------------------------------------------------
--
-- Lattice Semiconductor Corporation
-- 5555 NE Moore Court
-- Hillsboro, OR 97214
-- U.S.A
--
-- TEL: 1-800-Lattice (USA and Canada)
-- 408-826-6000 (other locations)
--
-- web: http://www.latticesemi.com/
-- email: techsupport@latticesemi.com
--
-- --------------------------------------------------------------------
--
-- This is the state machine module of the FPM DRAM controller reference
-- design.
--
-- --------------------------------------------------------------------
--
-- --------------------------------------------------------------------
--
-- Revision History :
-- --------------------------------------------------------------------
-- Ver :| Author :| Mod. Date :| Changes Made:
-- V1.0 :| K.L. :| 09/16/98 :| Pre-Release
-- V2.0 :| J.R. :| 12/17/01 :| Converted to VHDL
-- --------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity sm is port(
clk : in std_logic; -- Processor clock
dramsel : in std_logic; -- DRAM access in process when asserted
resetb : in std_logic; -- Reset signal
page_hit : in std_logic; -- Indicates page mode cycles requested
bnk1,bnk2 : in std_logic; -- Indicates which DRAM bank is addressed
upd, lod : in std_logic; -- Byte lane decodes
rwb : in std_logic; -- Processor Read/Write signal
ras1,ras2 : out std_logic; -- DRAM RAS signals
ucas,lcas : out std_logic; -- DRAM CAS signals
we : out std_logic; -- DRAM write enable signal
dsack1 : out std_logic; -- Data size/ack signals to CPU
dsack0 : out std_logic);
end sm;
architecture behavioral of sm is
-- Asynchronous versions of outputs to be synchronized to clk in the "sync_ctl" process
signal ras1a, ras2a : std_logic;
signal ucasa, lcasa : std_logic;
signal dsack1a, dsack0a : std_logic;
signal wea, refacka : std_logic;
-- Other internal signals
signal refreq : std_logic; -- Refresh Request
signal tc : std_logic; -- Refresh counter terminal count signal
signal q : std_logic_vector(8 downto 0); -- The refresh counter
signal pras1, pras2 : std_logic; -- Page mode RAS signals, used to hold
-- the RASx signal active between accesses
signal refack : std_logic;
signal ps, ns : std_logic_vector(3 downto 0);
--state declarations
constant idle : std_logic_vector(3 downto 0) := "0000";
constant rw1 : std_logic_vector(3 downto 0) := "0001";
constant rw2 : std_logic_vector(3 downto 0) := "0011";
constant rw3 : std_logic_vector(3 downto 0) := "0010";
constant cbr1 : std_logic_vector(3 downto 0) := "0111";
constant cbr2 : std_logic_vector(3 downto 0) := "0101";
constant cbr3 : std_logic_vector(3 downto 0) := "0100";
constant cbr4 : std_logic_vector(3 downto 0) := "1000";
constant prechg : std_logic_vector(3 downto 0) := "1001";
constant page1 : std_logic_vector(3 downto 0) := "1011";
constant page2 : std_logic_vector(3 downto 0) := "1010";
constant page3 : std_logic_vector(3 downto 0) := "1110";
constant dummy1 : std_logic_vector(3 downto 0) := "1111";
constant dummy2 : std_logic_vector(3 downto 0) := "1101";
constant dummy3 : std_logic_vector(3 downto 0) := "1100";
constant dummy4 : std_logic_vector(3 downto 0) := "0110";
begin
-- The DRAM controller state machine is implemented as a two-process FSM.
-- The first process is the asynchronous one that determines the next state
-- based upon current state and other inputs. Internal control signal levels
-- are also set in this process.
-- The second process is a small synchronous process that synchronizes the
-- state transitions and control signal outputs to the system clock.
---------------------------------------
------ Asynchronous process -----------
---------------------------------------
as_cont: process (dramsel, page_hit, refreq, ps, bnk1, bnk2, upd, lod, rwb, pras1, pras2)
begin
case ps is
when idle =>
ucasa <= '1';
lcasa <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
if (refreq = '1') then
ns <= cbr1; -- do a refresh cycle
wea <= '1';
dsack1a <= '1';
ras1a <= '1';
ras2a <= '1';
elsif (dramsel = '1') then
ns <= rw1; -- do a normal read/write cycle
wea <= rwb;
dsack1a <= '0';
ras1a <= not bnk1;
ras2a <= not bnk2;
else
ns <= idle;
wea <= '1';
dsack1a <= '1';
ras1a <= not bnk1;
ras2a <= not bnk2;
end if;
when rw1 => --dram access start
ras1a <= not bnk1;
ras2a <= not bnk2;
ucasa <= not upd;
lcasa <= not lod;
dsack1a <= '1'; --signal termination after one wait state
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
ns <= rw2;
when rw2 => --dsackx sampled at start of this state
ras1a <= not bnk1;
ras2a <= not bnk2;
ucasa <= '1';
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
ns <= rw3;
when rw3 => -- Read data sampled at start of this state
ucasa <= '1'; -- Write data written to DRAM on rising edge
lcasa <= '1'; -- of CAS.
dsack0a <= '1';
refacka <= '0';
if (page_hit = '1') then
ns <= page1; --goto page mode access
dsack1a <= '0';
ras1a <= pras1;
ras2a <= pras2;
wea <= rwb;
else
ns <= prechg; --goto dram access ready mode
dsack1a <= '1';
ras1a <= '1';
ras2a <= '1';
wea <= '1';
end if;
when page1 =>
ras1a <= pras1;
ras2a <= pras2;
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
if (dramsel = '1') then
ns <= page2;
ucasa <= not upd;
lcasa <= not lod; --data access in page mode
dsack1a <= '1'; --page mode use asynchronous dsack
else
ns <= page1;
ucasa <= '1';
lcasa <= '1';
dsack1a <= '0'; --page mode use asynchronous dsack
end if;
when page2=>
ras1a <= pras1;
ras2a <= pras2;
ucasa <= '1';
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
ns <= page3;
when page3 =>
ucasa <= '1';
lcasa <= '1'; --casb precharge
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
if (page_hit = '1') then
ns <= page1; --goto page1 state
dsack1a <= '0';
ras1a <= pras1;
ras2a <= pras2;
else
ns <= prechg; --goto precharge state
dsack1a <= '1';
ras1a <= '1';
ras2a <= '1';
end if;
when cbr1 => --cbr(casb before rasb refresh) mode start
ras1a <= '1';
ras2a <= '1';
ucasa <= '0'; --cas starts for refresh
lcasa <= '0';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '1'; --refresh request register clear
wea <= '1'; --refresh mode
ns <= cbr2;
when cbr2 =>
ras1a <= '0'; --ras follows next
ras2a <= '0';
ucasa <= '0';
lcasa <= '0';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= '1';
ns <= cbr3;
when cbr3 =>
ras1a <= '0';
ras2a <= '0';
ucasa <= '1'; -- deassert cas
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= '1';
ns <= cbr4;
when cbr4 =>
ras1a <= '1'; -- deassert ras
ras2a <= '1';
ucasa <= '1';
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= '1';
ns <= prechg;
when prechg =>
ras1a <= '1';
ras2a <= '1';
ucasa <= '1';
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= '1';
ns <= idle;
when others =>
ras1a <= '1';
ras2a <= '1';
ucasa <= '1';
lcasa <= '1';
dsack1a <= '1';
dsack0a <= '1';
refacka <= '0';
wea <= rwb;
ns <= idle;
end case;
end process;
---------------------------------------------
-------- Synchronous Process ---------------
---------------------------------------------
sync_ctl: process (clk, resetb) -- This is the synchronous process that controlls
begin -- the DRAM state machine.
if(resetb = '0') then
ps <= idle;
ras1 <= '1';
ras2 <= '1';
ucas <= '1';
lcas <= '1';
dsack1 <= '1';
dsack0 <= '1';
we <= '1';
refack <= '0';
elsif(clk'event and clk = '0') then -- state machine clocked on falling edge
ps <= ns; -- update the state machine state
ras1 <= ras1a; -- and assert the synchronous outputs
ras2 <= ras2a;
ucas <= ucasa;
lcas <= lcasa;
dsack1 <= dsack1a;
dsack0 <= dsack0a;
we <= wea;
refack <= refacka;
end if;
end process;
---------------------------------------
---- refresh counter
---- 9bits 15.6us interval
---------------------------------------
rfcnt: process(clk, refack, resetb)
begin
if (resetb = '0') then
q <= "000000000";
elsif (clk'event and clk = '0') then
if(refack = '1') then
q <= "000000000";
else
q <= q + 1;
end if;
end if;
end process;
-- 186hex = 110000110 binary = 390 decimal
-- assuming 25 MHz clock (40ns clock period)
-- 40ns (tCYC) x 390 = 15.6us is the refresh request rate.
tc <= '1' when q = "110000110" else
'0';
rreq: process (clk, tc, refack, resetb)
begin
if (resetb = '0') then
refreq <= '0';
elsif(clk'event and clk = '0') then
if refack = '1' then
refreq <= '0';
elsif tc = '1' then -- assert refreq when the terminal count (tc) is reached
refreq <= '1';
end if;
end if;
end process;
-- The PRASx signals are used to maintain the RASOx outputs
-- between the actual CPU accesses of a page mode access.
pras: process (clk, resetb)
begin
if (resetb = '0') then
pras1 <= '1';
pras2 <= '1';
elsif (clk'event and clk = '0') then
if ((ps = rw1) or (ps = page2)) then
pras1 <= not bnk1;
pras2 <= not bnk2;
end if;
end if;
end process;
end behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -