Files
FireBee_SVN/vhdl/rtl/vhdl/DDR/DDR_CTRL.vhd
Markus Fröschle 90bc4c409e more testbench code
2014-06-15 06:05:23 +00:00

807 lines
36 KiB
VHDL

----------------------------------------------------------------------
---- ----
---- This file is part of the 'Firebee' project. ----
---- http://acp.atari.org ----
---- ----
---- Description: ----
---- This design unit provides the DDR controller of the 'Firebee'----
---- computer. It is optimized for the use of an Altera Cyclone ----
---- FPGA (EP3C40F484). This IP-Core is based on the first edi- ----
---- tion of the Firebee configware originally provided by Fredi ----
---- Ashwanden and Wolfgang Förster. This release is in compa- ----
---- rision to the first edition completely written in VHDL. ----
---- ----
---- Author(s): ----
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2012 Fredi Aschwanden, Wolfgang Förster ----
---- ----
---- 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 2 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, write to the Free ----
---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
---- Boston, MA 02110-1301, USA. ----
---- ----
----------------------------------------------------------------------
--
-- Revision History
--
-- Revision 2K12B 20120801 WF
-- Initial Release of the second edition.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DDR_CTRL_V1 is
port(
CLK_MAIN : in std_logic;
DDR_SYNC_66M : in std_logic;
FB_ADR : in std_logic_vector(31 downto 0);
FB_CS1n : in std_logic;
FB_OEn : in std_logic;
FB_SIZE0 : in std_logic;
FB_SIZE1 : in std_logic;
FB_ALE : in std_logic;
FB_WRn : in std_logic;
FIFO_CLR : in std_logic;
VIDEO_RAM_CTR : in std_logic_vector(15 downto 0);
BLITTER_ADR : in std_logic_vector(31 downto 0);
BLITTER_SIG : in std_logic;
BLITTER_WR : in std_logic;
DDRCLK0 : in std_logic;
CLK_33M : in std_logic;
FIFO_MW : in std_logic_vector(8 downto 0);
VA : out std_logic_vector(12 downto 0);
VWEn : out std_logic;
VRASn : out std_logic;
VCSn : out std_logic;
VCKE : out std_logic;
VCASn : out std_logic;
FB_LE : out std_logic_vector(3 downto 0);
FB_VDOE : out std_logic_vector(3 downto 0);
SR_FIFO_WRE : out std_logic;
SR_DDR_FB : out std_logic;
SR_DDR_WR : out std_logic;
SR_DDRWR_D_SEL : out std_logic;
SR_VDMP : out std_logic_vector(7 downto 0);
VIDEO_DDR_TA : out std_logic;
SR_BLITTER_DACK : out std_logic;
BA : out std_logic_vector(1 downto 0);
DDRWR_D_SEL1 : out std_logic;
VDM_SEL : out std_logic_vector(3 downto 0);
DATA_IN : in std_logic_vector(31 downto 0);
DATA_OUT : out std_logic_vector(31 downto 16);
DATA_EN_H : out std_logic;
DATA_EN_L : out std_logic
);
end entity DDR_CTRL_V1;
architecture BEHAVIOUR of DDR_CTRL_V1 is
-- FIFO WATER MARK:
constant FIFO_LWM : std_logic_vector(8 downto 0) := "000000000";
constant FIFO_MWM : std_logic_vector(8 downto 0) := "011001000"; -- 200.
constant FIFO_HWM : std_logic_vector(8 downto 0) := "111110100"; -- 500.
type ACCESS_WIDTH_TYPE is (LONG, WORD, BYTE);
type DDR_ACCESS_TYPE is (CPU, FIFO, BLITTER, NONE);
type FB_REGDDR_TYPE is (FR_WAIT, FR_S0, FR_S1, FR_S2, FR_S3);
type DDR_SM_TYPE is (DS_T1, DS_T2A, DS_T2B, DS_T3, DS_N5, DS_N6, DS_N7, DS_N8, -- Start (normal 8 cycles total = 60ns).
DS_C2, DS_C3, DS_C4, DS_C5, DS_C6, DS_C7, -- Configuration.
DS_T4R, DS_T5R, -- Read CPU or BLITTER.
DS_T4W, DS_T5W, DS_T6W, DS_T7W, DS_T8W, DS_T9W, -- Write CPU or BLITTER.
DS_T4F, DS_T5F, DS_T6F, DS_T7F, DS_T8F, DS_T9F, DS_T10F, -- Read FIFO.
DS_CB6, DS_CB8, -- Close FIFO bank.
DS_R2, DS_R3, DS_R4, DS_R5, DS_R6); -- Refresh: 10 x 7.5ns = 75ns.
signal ACCESS_WIDTH : ACCESS_WIDTH_TYPE;
signal FB_REGDDR : FB_REGDDR_TYPE;
signal FB_REGDDR_NEXT : FB_REGDDR_TYPE;
signal DDR_ACCESS : DDR_ACCESS_TYPE;
signal DDR_STATE : DDR_SM_TYPE;
signal DDR_NEXT_STATE : DDR_SM_TYPE;
signal VCS_In : std_logic;
signal VCKE_I : std_logic;
signal BYTE_SEL : std_logic_vector(3 downto 0);
signal SR_FIFO_WRE_I : std_logic;
signal VCAS : std_logic;
signal VRAS : std_logic;
signal VWE : std_logic;
signal MCS : std_logic_vector(1 downto 0);
signal BUS_CYC : std_logic;
signal BUS_CYC_END : std_logic;
signal BLITTER_REQ : std_logic;
signal BLITTER_ROW_ADR : std_logic_vector(12 downto 0);
signal BLITTER_BA : std_logic_vector(1 downto 0);
signal BLITTER_COL_ADR : std_logic_vector(9 downto 0);
signal CPU_DDR_SYNC : std_logic;
signal CPU_ROW_ADR : std_logic_vector(12 downto 0);
signal CPU_BA : std_logic_vector(1 downto 0);
signal CPU_COL_ADR : std_logic_vector(9 downto 0);
signal CPU_REQ : std_logic;
signal DDR_SEL : std_logic;
signal DDR_CS : std_logic;
signal DDR_CONFIG : std_logic;
signal FIFO_REQ : std_logic;
signal FIFO_ROW_ADR : std_logic_vector(12 downto 0);
signal FIFO_BA : std_logic_vector(1 downto 0);
signal FIFO_COL_ADR : unsigned(9 downto 0);
signal FIFO_ACTIVE : std_logic;
signal FIFO_CLR_SYNC : std_logic;
signal VDM_SEL_I : std_logic_vector(3 downto 0);
signal CLEAR_FIFO_CNT : std_logic;
signal STOP : std_logic;
signal FIFO_BANK_OK : std_logic;
signal DDR_REFRESH_ON : std_logic;
signal DDR_REFRESH_CNT : unsigned(10 downto 0);
signal DDR_REFRESH_REQ : std_logic;
signal DDR_REFRESH_SIG : unsigned(3 downto 0);
signal REFRESH_TIME : std_logic;
signal VIDEO_BASE_L_D : std_logic_vector(7 downto 0);
signal VIDEO_BASE_L : std_logic;
signal VIDEO_BASE_M_D : std_logic_vector(7 downto 0);
signal VIDEO_BASE_M : std_logic;
signal VIDEO_BASE_H_D : std_logic_vector(7 downto 0);
signal VIDEO_BASE_H : std_logic;
signal VIDEO_BASE_X_D : std_logic_vector(2 downto 0);
signal VIDEO_ADR_CNT : unsigned(22 downto 0);
signal VIDEO_CNT_L : std_logic;
signal VIDEO_CNT_M : std_logic;
signal VIDEO_CNT_H : std_logic;
signal VIDEO_BASE_ADR : std_logic_vector(22 downto 0);
signal VIDEO_ACT_ADR : std_logic_vector(26 downto 0);
signal FB_ADR_I : std_logic_vector(32 downto 0);
signal VA_S : std_logic_vector(12 downto 0);
signal VA_P : std_logic_vector(12 downto 0);
signal BA_S : std_logic_vector(1 downto 0) ;
signal BA_P : std_logic_vector(1 downto 0);
signal TSIZ : std_logic_vector(1 downto 0);
begin
TSIZ <= FB_SIZE1 & FB_SIZE0;
with TSIZ select
ACCESS_WIDTH <= LONG when "11",
WORD when "00",
BYTE when others;
-- Byte selectors:
BYTE_SEL(0) <= '1' when ACCESS_WIDTH = LONG or ACCESS_WIDTH = WORD else
'1' when FB_ADR(1 downto 0) = "00" else '0'; -- Byte 0.
BYTE_SEL(1) <= '1' when ACCESS_WIDTH = LONG or ACCESS_WIDTH = WORD else
'1' when ACCESS_WIDTH = BYTE and FB_ADR(1) = '0' else -- High word.
'1' when FB_ADR(1 downto 0) = "01" else '0'; -- Byte 1.
BYTE_SEL(2) <= '1' when ACCESS_WIDTH = LONG or ACCESS_WIDTH = WORD else
'1' when FB_ADR(1 downto 0) = "10" else '0'; -- Byte 2.
BYTE_SEL(3) <= '1' when ACCESS_WIDTH = LONG or ACCESS_WIDTH = WORD else
'1' when ACCESS_WIDTH = BYTE and FB_ADR(1) = '1' else -- Low word.
'1' when FB_ADR(1 downto 0) = "11" else '0'; -- Byte 3.
---------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------ CPU READ (REG DDR => CPU) AND WRITE (CPU => REG DDR) ---------------------------------------------------------------------
FBCTRL_REG: process
begin
wait until CLK_MAIN = '1' and CLK_MAIN' event;
FB_REGDDR <= FB_REGDDR_NEXT;
end process FBCTRL_REG;
FBCTRL_DEC: process(FB_REGDDR, BUS_CYC, DDR_SEL, ACCESS_WIDTH, FB_WRn, DDR_CS)
begin
case FB_REGDDR is
when FR_WAIT =>
if BUS_CYC = '1' then
FB_REGDDR_NEXT <= FR_S0;
elsif DDR_SEL = '1' and ACCESS_WIDTH = LONG and FB_WRn = '0' then
FB_REGDDR_NEXT <= FR_S0;
else
FB_REGDDR_NEXT <= FR_WAIT;
end if;
when FR_S0 =>
if DDR_CS = '1' and ACCESS_WIDTH = LONG then
FB_REGDDR_NEXT <= FR_S1;
else
FB_REGDDR_NEXT <= FR_WAIT;
end if;
when FR_S1 =>
if DDR_CS = '1' then
FB_REGDDR_NEXT <= FR_S2;
else
FB_REGDDR_NEXT <= FR_WAIT;
end if;
when FR_S2 =>
if DDR_CS = '1' and BUS_CYC = '0' and ACCESS_WIDTH = LONG and FB_WRn = '0' then -- Eventually wait during long word access.
FB_REGDDR_NEXT <= FR_S2;
elsif DDR_CS = '1' then
FB_REGDDR_NEXT <= FR_S3;
else
FB_REGDDR_NEXT <= FR_WAIT;
end if;
when FR_S3 =>
FB_REGDDR_NEXT <= FR_WAIT;
end case;
end process FBCTRL_DEC;
-- Coldfire CPU access:
FB_LE(0) <= not FB_WRn when FB_REGDDR = FR_WAIT else
not FB_WRn when FB_REGDDR = FR_S0 and DDR_CS = '1' else '0';
FB_LE(1) <= not FB_WRn when FB_REGDDR = FR_S1 and DDR_CS = '1' else '0';
FB_LE(2) <= not FB_WRn when FB_REGDDR = FR_S2 and DDR_CS = '1' else '0';
FB_LE(3) <= not FB_WRn when FB_REGDDR = FR_S3 and DDR_CS = '1' else '0';
-- Video data access:
VIDEO_DDR_TA <= '1' when FB_REGDDR = FR_S0 and DDR_CS = '1' else
'1' when FB_REGDDR = FR_S1 and DDR_CS = '1' else
'1' when FB_REGDDR = FR_S2 and FB_REGDDR_NEXT = FR_S3 else
'1' when FB_REGDDR = FR_S3 and DDR_CS = '1' else '0';
-- FB_VDOE # VIDEO_OE.
-- Write access for video data:
FB_VDOE(0) <= '1' when FB_REGDDR = FR_S0 and DDR_CS = '1' and FB_OEn = '0' and DDR_CONFIG = '0' and ACCESS_WIDTH = LONG else
'1' when FB_REGDDR = FR_S0 and DDR_CS = '1' and FB_OEn = '0' and DDR_CONFIG = '0' and ACCESS_WIDTH /= LONG and CLK_MAIN = '0' else '0';
FB_VDOE(1) <= '1' when FB_REGDDR = FR_S1 and DDR_CS = '1' and FB_OEn = '0' and DDR_CONFIG = '0' else '0';
FB_VDOE(2) <= '1' when FB_REGDDR = FR_S2 and DDR_CS = '1' and FB_OEn = '0' and DDR_CONFIG = '0' else '0';
FB_VDOE(3) <= '1' when FB_REGDDR = FR_S3 and DDR_CS = '1' and FB_OEn = '0' and DDR_CONFIG = '0' and CLK_MAIN = '0' else '0';
BUS_CYC_END <= '1' when FB_REGDDR = FR_S0 and DDR_CS = '1' and ACCESS_WIDTH /= LONG else
'1' when FB_REGDDR = FR_S3 and DDR_CS = '1' else '0';
---------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------ DDR State Machine --------------------------------------------------------------------------------------
DDR_STATE_REG: process
begin
wait until DDRCLK0 = '1' and DDRCLK0' event;
DDR_STATE <= DDR_NEXT_STATE;
end process DDR_STATE_REG;
DDR_STATE_DEC: process(DDR_STATE, DDR_REFRESH_REQ, CPU_DDR_SYNC, DDR_CONFIG, FB_WRn, DDR_ACCESS, BLITTER_WR, FIFO_REQ, FIFO_BANK_OK,
FIFO_MW, CPU_REQ, VIDEO_ADR_CNT, DDR_SEL, FB_SIZE1, FB_SIZE0, DATA_IN, FIFO_BA, DDR_REFRESH_SIG)
begin
case DDR_STATE is
when DS_T1 =>
if DDR_REFRESH_REQ = '1' then
DDR_NEXT_STATE <= DS_R2;
elsif CPU_DDR_SYNC = '1' and DDR_CONFIG = '1' then -- Synchronous start.
DDR_NEXT_STATE <= DS_C2;
elsif CPU_DDR_SYNC = '1' and CPU_REQ = '1' then -- Synchronous start.
DDR_NEXT_STATE <= DS_T2B;
elsif CPU_DDR_SYNC = '1' then
DDR_NEXT_STATE <= DS_T2A;
else
DDR_NEXT_STATE <= DS_T1; -- Synchronize.
end if;
when DS_T2A => -- Fast access, in this case page is always not ok.
DDR_NEXT_STATE <= DS_T3;
when DS_T2B =>
DDR_NEXT_STATE <= DS_T3;
when DS_T3 =>
if DDR_ACCESS = CPU and FB_WRn = '0' then
DDR_NEXT_STATE <= DS_T4W;
elsif DDR_ACCESS = BLITTER and BLITTER_WR = '1' then
DDR_NEXT_STATE <= DS_T4W;
elsif DDR_ACCESS = CPU then -- CPU?
DDR_NEXT_STATE <= DS_T4R;
elsif DDR_ACCESS = FIFO then -- FIFO?
DDR_NEXT_STATE <= DS_T4F;
elsif DDR_ACCESS = BLITTER then
DDR_NEXT_STATE <= DS_T4R;
else
DDR_NEXT_STATE <= DS_N8;
end if;
-- Read:
when DS_T4R =>
DDR_NEXT_STATE <= DS_T5R;
when DS_T5R =>
if FIFO_REQ = '1' and FIFO_BANK_OK = '1' then -- Insert FIFO read, when bank ok.
DDR_NEXT_STATE <= DS_T6F;
else
DDR_NEXT_STATE <= DS_CB6;
end if;
-- Write:
when DS_T4W =>
DDR_NEXT_STATE <= DS_T5W;
when DS_T5W =>
DDR_NEXT_STATE <= DS_T6W;
when DS_T6W =>
DDR_NEXT_STATE <= DS_T7W;
when DS_T7W =>
DDR_NEXT_STATE <= DS_T8W;
when DS_T8W =>
DDR_NEXT_STATE <= DS_T9W;
when DS_T9W =>
if FIFO_REQ = '1' and FIFO_BANK_OK = '1' then
DDR_NEXT_STATE <= DS_T6F;
else
DDR_NEXT_STATE <= DS_CB6;
end if;
-- FIFO read:
when DS_T4F =>
DDR_NEXT_STATE <= DS_T5F;
when DS_T5F =>
if FIFO_REQ = '1' then
DDR_NEXT_STATE <= DS_T6F;
else
DDR_NEXT_STATE <= DS_CB6; -- Leave open.
end if;
when DS_T6F =>
DDR_NEXT_STATE <= DS_T7F;
when DS_T7F =>
if CPU_REQ = '1' and FIFO_MW > FIFO_LWM then
DDR_NEXT_STATE <= DS_CB8; -- Close bank.
elsif FIFO_REQ = '1' and VIDEO_ADR_CNT(7 downto 0) = x"FF" then -- New page?
DDR_NEXT_STATE <= DS_CB8; -- Close bank.
elsif FIFO_REQ = '1' then
DDR_NEXT_STATE <= DS_T8F;
else
DDR_NEXT_STATE <= DS_CB8; -- Close bank.
end if;
when DS_T8F =>
if FIFO_MW < FIFO_LWM then -- Emergency?
DDR_NEXT_STATE <= DS_T5F; -- Yes!
else
DDR_NEXT_STATE <= DS_T9F;
end if;
when DS_T9F =>
if FIFO_REQ = '1' and VIDEO_ADR_CNT(7 downto 0) = x"FF" then -- New page?
DDR_NEXT_STATE <= DS_CB6; -- Close bank.
elsif FIFO_REQ = '1' then
DDR_NEXT_STATE <= DS_T10F;
else
DDR_NEXT_STATE <= DS_CB6; -- Close bank.
end if;
when DS_T10F =>
if DDR_SEL = '1' and (FB_WRn = '1' or (FB_SIZE0 and FB_SIZE1) = '0') and DATA_IN(13 downto 12) /= FIFO_BA then
DDR_NEXT_STATE <= DS_T3;
else
DDR_NEXT_STATE <= DS_T7F;
end if;
-- Configuration cycles:
when DS_C2 =>
DDR_NEXT_STATE <= DS_C3;
when DS_C3 =>
DDR_NEXT_STATE <= DS_C4;
when DS_C4 =>
if CPU_REQ = '1' then
DDR_NEXT_STATE <= DS_C5;
else
DDR_NEXT_STATE <= DS_T1;
end if;
when DS_C5 =>
DDR_NEXT_STATE <= DS_C6;
when DS_C6 =>
DDR_NEXT_STATE <= DS_C7;
when DS_C7 =>
DDR_NEXT_STATE <= DS_N8;
-- Close FIFO bank.
when DS_CB6 =>
DDR_NEXT_STATE <= DS_N7;
when DS_CB8 =>
DDR_NEXT_STATE <= DS_T1;
-- Refresh 70ns = ten cycles.
when DS_R2 =>
if DDR_REFRESH_SIG = x"9" then -- One cycle delay to close all banks.
DDR_NEXT_STATE <= DS_R4;
else
DDR_NEXT_STATE <= DS_R3;
end if;
when DS_R3 =>
DDR_NEXT_STATE <= DS_R4;
when DS_R4 =>
DDR_NEXT_STATE <= DS_R5;
when DS_R5 =>
DDR_NEXT_STATE <= DS_R6;
when DS_R6 =>
DDR_NEXT_STATE <= DS_N5;
-- Loop:
when DS_N5 =>
DDR_NEXT_STATE <= DS_N6;
when DS_N6 =>
DDR_NEXT_STATE <= DS_N7;
when DS_N7 =>
DDR_NEXT_STATE <= DS_N8;
when DS_N8 =>
DDR_NEXT_STATE <= DS_T1;
end case;
end process DDR_STATE_DEC;
P_CLK0: process
begin
wait until DDRCLK0 = '1' and DDRCLK0' event;
-- Default assignments;
DDR_ACCESS <= NONE;
SR_FIFO_WRE_I <= '0';
SR_VDMP <= x"00";
SR_DDR_WR <= '0';
SR_DDRWR_D_SEL <= '0';
MCS <= MCS(0) & CLK_MAIN;
BLITTER_REQ <= BLITTER_SIG and not DDR_CONFIG and VCKE_I and not VCS_In;
FIFO_CLR_SYNC <= FIFO_CLR;
CLEAR_FIFO_CNT <= FIFO_CLR_SYNC or not FIFO_ACTIVE;
STOP <= FIFO_CLR_SYNC or CLEAR_FIFO_CNT;
if FIFO_MW < FIFO_MWM then
FIFO_REQ <= '1';
elsif FIFO_MW < FIFO_HWM and FIFO_REQ = '1' then
FIFO_REQ <= '1';
elsif FIFO_ACTIVE = '1' and CLEAR_FIFO_CNT = '0' and STOP = '0' and DDR_CONFIG = '0' and VCKE_I = '1' and VCS_In = '0' then
FIFO_REQ <= '1';
else
FIFO_REQ <= '1';
end if;
if CLEAR_FIFO_CNT = '1' then
VIDEO_ADR_CNT <= unsigned(VIDEO_BASE_ADR);
elsif SR_FIFO_WRE_I = '1' then
VIDEO_ADR_CNT <= VIDEO_ADR_CNT + 1;
end if;
if MCS = "10" and VCKE_I = '1' and VCS_In = '0' then
CPU_DDR_SYNC <= '1';
else
CPU_DDR_SYNC <= '0';
end if;
if DDR_REFRESH_SIG /= x"0" and DDR_REFRESH_ON = '1' and DDR_CONFIG = '0' and REFRESH_TIME = '1' then
DDR_REFRESH_REQ <= '1';
else
DDR_REFRESH_REQ <= '0';
end if;
if DDR_REFRESH_CNT = "00000000000" and CLK_MAIN = '0' then
REFRESH_TIME <= '1';
else
REFRESH_TIME <= '0';
end if;
if REFRESH_TIME = '1' and DDR_REFRESH_ON = '1' and DDR_CONFIG = '0' then
DDR_REFRESH_SIG <= x"9";
elsif DDR_STATE = DS_R6 and DDR_REFRESH_ON = '1' and DDR_CONFIG = '0' then
DDR_REFRESH_SIG <= DDR_REFRESH_SIG - 1;
else
DDR_REFRESH_SIG <= x"0";
end if;
if BUS_CYC_END = '1' then
BUS_CYC <= '0';
elsif DDR_STATE = DS_T1 and CPU_DDR_SYNC = '1' and CPU_REQ = '1' then
BUS_CYC <= '1';
elsif DDR_STATE = DS_T2A and DDR_SEL = '1' and FB_WRn = '0' then
BUS_CYC <= '1';
elsif DDR_STATE = DS_T2A and DDR_SEL = '1' and (FB_SIZE0 = '0' or FB_SIZE1= '0') then
BUS_CYC <= '1';
elsif DDR_STATE = DS_T2B then
BUS_CYC <= '1';
elsif DDR_STATE = DS_T10F and FB_WRn = '0' and DATA_IN(13 downto 12) = FIFO_BA then
BUS_CYC <= '1';
elsif DDR_STATE = DS_T10F and (FB_SIZE0 = '0' or FB_SIZE1= '0') and DATA_IN(13 downto 12) = FIFO_BA then
BUS_CYC <= '1';
elsif DDR_STATE = DS_C3 then
BUS_CYC <= CPU_REQ;
end if;
if DDR_STATE = DS_T1 and CPU_DDR_SYNC = '1' and CPU_REQ = '1' then
VA_S <= CPU_ROW_ADR;
BA_S <= CPU_BA;
DDR_ACCESS <= CPU;
elsif DDR_STATE = DS_T1 and CPU_DDR_SYNC = '1' and FIFO_REQ = '1' then
VA_P <= FIFO_ROW_ADR;
BA_P <= FIFO_BA;
DDR_ACCESS <= FIFO;
elsif DDR_STATE = DS_T1 and CPU_DDR_SYNC = '1' and BLITTER_REQ = '0' then
VA_P <= BLITTER_ROW_ADR;
BA_P <= BLITTER_BA;
DDR_ACCESS <= BLITTER;
elsif DDR_STATE = DS_T2A and DDR_SEL = '1' and FB_WRn = '0' then
VA_S(10) <= '1';
DDR_ACCESS <= CPU;
elsif DDR_STATE = DS_T2A and DDR_SEL = '1' and (FB_SIZE0 = '0' or FB_SIZE1= '0') then
VA_S(10) <= '1';
DDR_ACCESS <= CPU;
elsif DDR_STATE = DS_T2A then
-- ?? mfro
VA_S(10) <= not (FIFO_ACTIVE and FIFO_REQ);
DDR_ACCESS <= FIFO;
FIFO_BANK_OK <= FIFO_ACTIVE and FIFO_REQ;
-- ?? mfro BLITTER_AC <= BLITTER_ACTIVE and BLITTER_REQ;
elsif DDR_STATE = DS_T2B then
FIFO_BANK_OK <= '0';
elsif DDR_STATE = DS_T3 then
VA_S(10) <= VA_S(10);
if (FB_WRn = '0' and DDR_ACCESS = CPU) or (BLITTER_WR = '1' and DDR_ACCESS = BLITTER) then
VA_S(9 downto 0) <= CPU_COL_ADR;
BA_S <= CPU_BA;
elsif FIFO_ACTIVE = '1' then
VA_S(9 downto 0) <= std_logic_vector(FIFO_COL_ADR);
BA_S <= FIFO_BA;
elsif DDR_ACCESS = BLITTER then
VA_S(9 downto 0) <= BLITTER_COL_ADR;
BA_S <= BLITTER_BA;
end if;
elsif DDR_STATE = DS_T4R then
-- mfro SR_DDR_FB <= CPU_AC;
-- mfro SR_BLITTER_DACK <= BLITTER_AC;
elsif DDR_STATE = DS_T5R and FIFO_REQ = '1' and FIFO_BANK_OK = '1' then
VA_S(10) <= '0';
VA_S(9 downto 0) <= std_logic_vector(FIFO_COL_ADR);
BA_S <= FIFO_BA;
elsif DDR_STATE = DS_T5R then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T4W then
VA_S(10) <= VA_S(10);
-- mfro SR_BLITTER_DACK <= BLITTER_AC;
elsif DDR_STATE = DS_T5W then
VA_S(10) <= VA_S(10);
if DDR_ACCESS = CPU then
VA_S(9 downto 0) <= CPU_COL_ADR;
BA_S <= CPU_BA;
elsif DDR_ACCESS = BLITTER then
VA_S(9 downto 0) <= BLITTER_COL_ADR;
BA_S <= BLITTER_BA;
end if;
if DDR_ACCESS = BLITTER and FB_SIZE1 = '1' and FB_SIZE0 = '1' then
SR_VDMP <= BYTE_SEL & x"F";
elsif DDR_ACCESS = BLITTER then
SR_VDMP <= BYTE_SEL & x"0";
else
SR_VDMP <= BYTE_SEL & x"0";
end if;
elsif DDR_STATE = DS_T6W then
SR_DDR_WR <= '1';
SR_DDRWR_D_SEL <= '1';
if DDR_ACCESS = BLITTER or (FB_SIZE1 = '1' and FB_SIZE0 = '1') then
SR_VDMP <= x"FF";
else
SR_VDMP <= x"00";
end if;
elsif DDR_STATE = DS_T7W then
SR_DDR_WR <= '1';
SR_DDRWR_D_SEL <= '1';
elsif DDR_STATE = DS_T9W and FIFO_REQ = '1' and FIFO_BANK_OK = '1' then
VA_S(10) <= '0';
VA_S(9 downto 0) <= std_logic_vector(FIFO_COL_ADR);
BA_S <= FIFO_BA;
elsif DDR_STATE = DS_T9W then
VA_S(10) <= '0';
elsif DDR_STATE = DS_T4F then
SR_FIFO_WRE_I <= '1';
elsif DDR_STATE = DS_T5F and FIFO_REQ = '1' and VIDEO_ADR_CNT(7 downto 0) = x"FF" then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T5F and FIFO_REQ = '1' then
VA_S(10) <= '0';
VA_S(9 downto 0) <= std_logic_vector(FIFO_COL_ADR + "100");
BA_S <= FIFO_BA;
elsif DDR_STATE = DS_T5F then
VA_S(10) <= '0';
elsif DDR_STATE = DS_T6F then
SR_FIFO_WRE_I <= '1';
elsif DDR_STATE = DS_T7F and CPU_REQ = '1' and FIFO_MW > FIFO_LWM then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T7F and FIFO_REQ = '1' and VIDEO_ADR_CNT(7 downto 0) = x"FF" then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T7F and FIFO_REQ = '1' then
VA_S(10) <= '0';
VA_S(9 downto 0) <= std_logic_vector(FIFO_COL_ADR + "100");
BA_S <= FIFO_BA;
elsif DDR_STATE = DS_T7F then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T9F and FIFO_REQ = '1' and VIDEO_ADR_CNT(7 downto 0) = x"FF" then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T9F and FIFO_REQ = '1' then
VA_P(10) <= '0';
VA_P(9 downto 0) <= std_logic_vector(FIFO_COL_ADR + "100");
BA_P <= FIFO_BA;
elsif DDR_STATE = DS_T9F then
VA_S(10) <= '1';
elsif DDR_STATE = DS_T10F and FB_WRn = '0' and DATA_IN(13 downto 12) = FIFO_BA then
VA_S(10) <= '1';
DDR_ACCESS <= CPU;
elsif DDR_STATE = DS_T10F and (FB_SIZE0 = '0' or FB_SIZE1= '0') and DATA_IN(13 downto 12) = FIFO_BA then
VA_S(10) <= '1';
DDR_ACCESS <= CPU;
elsif DDR_STATE = DS_T10F then
SR_FIFO_WRE_I <= '1';
elsif DDR_STATE = DS_C6 then
VA_S <= DATA_IN(12 downto 0);
BA_S <= DATA_IN(14 downto 13);
elsif DDR_STATE = DS_CB6 then
FIFO_BANK_OK <= '0';
elsif DDR_STATE = DS_CB8 then
FIFO_BANK_OK <= '0';
elsif DDR_STATE = DS_R2 then
FIFO_BANK_OK <= '0';
else
end if;
end process P_CLK0;
DDR_SEL <= '1' when FB_ALE = '1' and DATA_IN(31 downto 30) = "01" else '0';
P_DDR_CS: process
begin
wait until CLK_MAIN = '1' and CLK_MAIN' event;
if FB_ALE = '1' then
DDR_CS <= DDR_SEL;
end if;
end process P_DDR_CS;
P_CPU_REQ: process
begin
wait until DDR_SYNC_66M = '1' and DDR_SYNC_66M' event;
if DDR_SEL = '1' and FB_WRn = '1' and DDR_CONFIG = '0' then
CPU_REQ <= '1';
elsif DDR_SEL = '1' and FB_SIZE1 = '0' and FB_SIZE1 = '0' and DDR_CONFIG = '0' then -- Start when not config and not long word access.
CPU_REQ <= '1';
elsif DDR_SEL = '1' and FB_SIZE1 = '0' and FB_SIZE1 = '1' and DDR_CONFIG = '0' then -- Start when not config and not long word access.
CPU_REQ <= '1';
elsif DDR_SEL = '1' and FB_SIZE1 = '1' and FB_SIZE1 = '0' and DDR_CONFIG = '0' then -- Start when not config and not long word access.
CPU_REQ <= '1';
elsif DDR_SEL = '1' and DDR_CONFIG = '1' then -- Config, start immediately.
CPU_REQ <= '1';
elsif FB_REGDDR = FR_S1 and FB_WRn = '0' then -- Long word write later.
CPU_REQ <= '1';
elsif FB_REGDDR /= FR_S1 and FB_REGDDR /= FR_S3 and BUS_CYC_END = '0' and BUS_CYC = '0' then -- Halt, bus cycle in progress or ready.
CPU_REQ <= '0';
end if;
end process P_CPU_REQ;
P_REFRESH: process
-- Refresh: Always 8 at a time every 7.8us.
-- 7.8us x 8 = 62.4us = 2059 -> 2048 @ 33MHz.
begin
wait until CLK_33M = '1' and CLK_33M' event;
DDR_REFRESH_CNT <= DDR_REFRESH_CNT + 1; -- Count 0 to 2047.
end process P_REFRESH;
SR_FIFO_WRE <= SR_FIFO_WRE_I;
VA <= DATA_IN(26 downto 14) when DDR_STATE = DS_T2A and DDR_SEL = '1' and FB_WRn = '0' else
DATA_IN(26 downto 14) when DDR_STATE = DS_T2A and DDR_SEL = '1' and (FB_SIZE0 = '0' or FB_SIZE1= '0') else
VA_P when DDR_STATE = DS_T2A else
DATA_IN(26 downto 14) when DDR_STATE = DS_T10F and FB_WRn = '0' and DATA_IN(13 downto 12) = FIFO_BA else
DATA_IN(26 downto 14) when DDR_STATE = DS_T10F and (FB_SIZE0 = '0' or FB_SIZE1= '0') and DATA_IN(13 downto 12) = FIFO_BA else
VA_P when DDR_STATE = DS_T10F else
"0010000000000" when DDR_STATE = DS_R2 and DDR_REFRESH_SIG = x"9" else VA_S;
BA <= DATA_IN(13 downto 12) when DDR_STATE = DS_T2A and DDR_SEL = '1' and FB_WRn = '0' else
DATA_IN(13 downto 12) when DDR_STATE = DS_T2A and DDR_SEL = '1' and (FB_SIZE0 = '0' or FB_SIZE1= '0') else
BA_P when DDR_STATE = DS_T2A else
DATA_IN(13 downto 12) when DDR_STATE = DS_T10F and FB_WRn = '0' and DATA_IN(13 downto 12) = FIFO_BA else
DATA_IN(13 downto 12) when DDR_STATE = DS_T10F and (FB_SIZE0 = '0' or FB_SIZE1= '0') and DATA_IN(13 downto 12) = FIFO_BA else
BA_P when DDR_STATE = DS_T10F else BA_S;
VRAS <= '1' when DDR_STATE = DS_T2A and DDR_SEL = '1' and FB_WRn = '0' else
'1' when DDR_STATE = DS_T2A and DDR_SEL = '1' and (FB_SIZE0 = '0' or FB_SIZE1= '0') else
'1' when DDR_STATE = DS_T2A and DDR_ACCESS = FIFO and FIFO_REQ = '1' else
'1' when DDR_STATE = DS_T2A and DDR_ACCESS = BLITTER and BLITTER_REQ = '1' else
'1' when DDR_STATE = DS_T2B else
'1' when DDR_STATE = DS_T10F and FB_WRn = '0' and DATA_IN(13 downto 12) = FIFO_BA else
'1' when DDR_STATE = DS_T10F and (FB_SIZE0 = '0' or FB_SIZE1= '0') and DATA_IN(13 downto 12) = FIFO_BA else
DATA_IN(18) and not FB_WRn and not FB_SIZE0 and not FB_SIZE1 when DDR_STATE = DS_C7 else
'1' when DDR_STATE = DS_CB6 else
'1' when DDR_STATE = DS_CB8 else
'1' when DDR_STATE = DS_R2 else '0';
VCAS <= '1' when DDR_STATE = DS_T4R else
'1' when DDR_STATE = DS_T6W else
'1' when DDR_STATE = DS_T4F else
'1' when DDR_STATE = DS_T6F else
'1' when DDR_STATE = DS_T8F else
'1' when DDR_STATE = DS_T10F and VRAS = '0' else
DATA_IN(17) and not FB_WRn and not FB_SIZE0 and not FB_SIZE1 when DDR_STATE = DS_C7 else
'1' when DDR_STATE = DS_R2 and DDR_REFRESH_SIG /= x"9" else '0';
VWE <= '1' when DDR_STATE = DS_T6W else
DATA_IN(16) and not FB_WRn and not FB_SIZE0 and not FB_SIZE1 when DDR_STATE = DS_C7 else
'1' when DDR_STATE = DS_CB6 else
'1' when DDR_STATE = DS_CB8 else
'1' when DDR_STATE = DS_R2 and DDR_REFRESH_SIG = x"9" else '0';
-- DDR controller:
-- VIDEO RAM CONTROL REGISTER (is in VIDEO_MUX_CTR)
-- $F0000400: BIT 0: VCKE; 1: not nVCS ;2:REFRESH ON , (0=FIFO and CNT CLEAR);
-- 3: CONFIG; 8: FIFO_ACTIVE;
VCKE <= VCKE_I;
VCKE_I <= VIDEO_RAM_CTR(0);
VCSn <= VCS_In;
VCS_In <= not VIDEO_RAM_CTR(1);
DDR_REFRESH_ON <= VIDEO_RAM_CTR(2);
DDR_CONFIG <= VIDEO_RAM_CTR(3);
FIFO_ACTIVE <= VIDEO_RAM_CTR(8);
CPU_ROW_ADR <= FB_ADR(26 downto 14);
CPU_BA <= FB_ADR(13 downto 12);
CPU_COL_ADR <= FB_ADR(11 downto 2);
VRASn <= not VRAS;
VCASn <= not VCAS;
VWEn <= not VWE;
DDRWR_D_SEL1 <= '1' when DDR_ACCESS = BLITTER else '0';
BLITTER_ROW_ADR <= BLITTER_ADR(26 downto 14);
BLITTER_BA <= BLITTER_ADR(13 downto 12);
BLITTER_COL_ADR <= BLITTER_ADR(11 downto 2);
FIFO_ROW_ADR <= std_logic_vector(VIDEO_ADR_CNT(22 downto 10));
FIFO_BA <= std_logic_vector(VIDEO_ADR_CNT(9 downto 8));
FIFO_COL_ADR <= VIDEO_ADR_CNT(7 downto 0) & "00";
VIDEO_BASE_ADR(22 downto 20) <= VIDEO_BASE_X_D;
VIDEO_BASE_ADR(19 downto 12) <= VIDEO_BASE_H_D;
VIDEO_BASE_ADR(11 downto 4) <= VIDEO_BASE_M_D;
VIDEO_BASE_ADR(3 downto 0) <= VIDEO_BASE_L_D(7 downto 4);
VDM_SEL <= VDM_SEL_I;
VDM_SEL_I <= VIDEO_BASE_L_D(3 downto 0);
-- Current video address:
VIDEO_ACT_ADR(26 downto 4) <= std_logic_vector(VIDEO_ADR_CNT - unsigned(FIFO_MW));
VIDEO_ACT_ADR(3 downto 0) <= VDM_SEL_I;
P_VIDEO_REGS: process
-- Video registers.
begin
wait until CLK_MAIN = '1' and CLK_MAIN' event;
if VIDEO_BASE_L = '1' and FB_WRn = '0' and BYTE_SEL(1) = '1' then
VIDEO_BASE_L_D <= DATA_IN(23 downto 16); -- 16 byte boarders.
end if;
if VIDEO_BASE_M = '1' and FB_WRn = '0' and BYTE_SEL(3) = '1' then
VIDEO_BASE_M_D <= DATA_IN(23 downto 16);
end if;
if VIDEO_BASE_H = '1' and FB_WRn = '0' and BYTE_SEL(1) = '1' then
VIDEO_BASE_H_D <= DATA_IN(23 downto 16);
end if;
if VIDEO_BASE_H = '1' and FB_WRn = '0' and BYTE_SEL(0) = '1' then
VIDEO_BASE_X_D <= DATA_IN(26 downto 24);
end if;
end process P_VIDEO_REGS;
FB_ADR_I <= FB_ADR & '0';
VIDEO_BASE_L <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"820D" else '0'; -- x"FF820D".
VIDEO_BASE_M <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"8204" else '0'; -- x"FF8203".
VIDEO_BASE_H <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"8202" else '0'; -- x"FF8201".
VIDEO_CNT_L <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"8208" else '0'; -- x"FF8209".
VIDEO_CNT_M <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"8206" else '0'; -- x"FF8207".
VIDEO_CNT_H <= '1' when FB_CS1n = '0' and FB_ADR_I(15 downto 0) = x"8204" else '0'; -- x"FF8205".
DATA_OUT(31 downto 24) <= "00000" & VIDEO_BASE_X_D when VIDEO_BASE_H = '1' else
"00000" & VIDEO_ACT_ADR(26 downto 24) when VIDEO_CNT_H = '1' else (others => '0');
DATA_EN_H <= (VIDEO_BASE_H or VIDEO_CNT_H) and not FB_OEn;
DATA_OUT(23 downto 16) <= VIDEO_BASE_L_D when VIDEO_BASE_L = '1' else
VIDEO_BASE_M_D when VIDEO_BASE_M = '1' else
VIDEO_BASE_H_D when VIDEO_BASE_H = '1' else
VIDEO_ACT_ADR(7 downto 0) when VIDEO_CNT_L = '1' else
VIDEO_ACT_ADR(15 downto 8) when VIDEO_CNT_M = '1' else
VIDEO_ACT_ADR(23 downto 16) when VIDEO_CNT_H = '1' else (others => '0');
DATA_EN_L <= (VIDEO_BASE_L or VIDEO_BASE_M or VIDEO_BASE_H or VIDEO_CNT_L or VIDEO_CNT_M or VIDEO_CNT_H) and not FB_OEn;
end architecture BEHAVIOUR;
-- VA : Video DDR address multiplexed.
-- VA_P : latched VA, wenn FIFO_AC, BLITTER_AC.
-- VA_S : latch for default VA.
-- BA : Video DDR bank address multiplexed.
-- BA_P : latched BA, wenn FIFO_AC, BLITTER_AC.
-- BA_S : latch for default BA.
--
--FB_SIZE ersetzen.