- CRLF git-svn-id: http://moon:8086/svn/vhdl/trunk@1052 cc03376c-175c-47c8-b038-4cd826a8556b
193 lines
6.5 KiB
VHDL
193 lines
6.5 KiB
VHDL
LIBRARY IEEE;
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
|
USE IEEE.NUMERIC_STD.ALL;
|
|
|
|
Library UNISIM;
|
|
use UNISIM.vcomponents.all;
|
|
|
|
ENTITY ssram_port_wb IS
|
|
Generic
|
|
(
|
|
latency : natural := 2; -- clock cycles
|
|
addr_width : natural := 20;
|
|
data_width : natural := 32;
|
|
parity_width : natural := 4
|
|
);
|
|
Port
|
|
(
|
|
-- J-Bus domain
|
|
CLK_I : in STD_LOGIC;
|
|
RST_I : in STD_LOGIC;
|
|
CYC_I : in STD_LOGIC;
|
|
STB_I : in STD_LOGIC;
|
|
SEL_I : in unsigned(3 downto 0);
|
|
WE_I : in STD_LOGIC;
|
|
ACK_O : out STD_LOGIC;
|
|
SRDY_O : out STD_LOGIC;
|
|
MRDY_I : in STD_LOGIC;
|
|
ADDR_I : in unsigned(31 downto 0);
|
|
DAT_I : in unsigned(31 downto 0);
|
|
DAT_O : out unsigned(31 downto 0);
|
|
|
|
-- Sync SRAM domain
|
|
ssram_clk_o : out std_logic;
|
|
ssram_clk_fb : in std_logic;
|
|
ssram_cke_n : out std_logic;
|
|
ssram_ce_n : out std_logic;
|
|
port_bsyi : in std_logic;
|
|
port_bsyo : out std_logic;
|
|
port_a : out unsigned(addr_width-1 downto 0);
|
|
port_di : in unsigned(data_width-1 downto 0);
|
|
port_do : out unsigned(data_width-1 downto 0);
|
|
port_d_drv : out STD_LOGIC;
|
|
port_wr : out STD_LOGIC;
|
|
port_rd : out STD_LOGIC;
|
|
ssram_adv : out std_logic;
|
|
ssram_mode : out std_logic;
|
|
ssram_zz : out std_logic;
|
|
ssram_dp : inout unsigned(parity_width-1 downto 0);
|
|
ssram_bw_n : out unsigned(3 downto 0)
|
|
);
|
|
END ssram_port_wb;
|
|
|
|
ARCHITECTURE behavior OF ssram_port_wb IS
|
|
|
|
constant topad : time := 3 ns;
|
|
subtype ssram_d_t is unsigned(data_width+parity_width-1 downto 0);
|
|
type data_pipe_t is array (latency downto 0) of ssram_d_t;
|
|
|
|
signal ssram_clk : std_logic;
|
|
signal dcm_locked : std_logic;
|
|
signal dcm_clk0 : std_logic;
|
|
signal dcm_clk1 : std_logic;
|
|
signal data_en : std_logic;
|
|
signal drive : std_logic;
|
|
signal busy : std_logic;
|
|
signal bsy_pipe : unsigned(latency downto 0);
|
|
signal vld_pipe : unsigned(latency downto 0);
|
|
signal drive_pipe : unsigned(latency downto 0);
|
|
signal data_pipe : data_pipe_t;
|
|
signal ssram_dout : ssram_d_t;
|
|
|
|
begin
|
|
|
|
SRDY_O <= CYC_I and dcm_locked and not port_bsyi;
|
|
ACK_O <= vld_pipe(vld_pipe'left);
|
|
DAT_O(data_width-1 downto 0) <= port_di;
|
|
|
|
data_en <= CYC_I and STB_I and not port_bsyi;
|
|
ssram_dout <= "0000" & DAT_I(data_width-1 downto 0);
|
|
drive <= drive_pipe(drive_pipe'left);
|
|
|
|
ssram_clk_o <= ssram_clk after topad;
|
|
ssram_cke_n <= not dcm_locked after topad;
|
|
|
|
port_a <= ADDR_I(addr_width-1 downto 0);
|
|
port_do <= data_pipe(data_pipe'left-1)(data_width-1 downto 0);
|
|
port_d_drv <= drive_pipe(drive_pipe'left-1);
|
|
port_wr <= not (WE_I and data_en);
|
|
port_rd <= not (vld_pipe(vld_pipe'left-2) or vld_pipe(vld_pipe'left-1));
|
|
busy <= '1' when bsy_pipe /= (latency downto 0 => '0') else '0';
|
|
port_bsyo <= busy or data_en;
|
|
|
|
inst_clock_out : ODDR
|
|
generic map
|
|
(
|
|
DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
|
)
|
|
port map (
|
|
Q => ssram_clk, -- 1-bit DDR output
|
|
C => dcm_clk1, -- 1-bit clock input
|
|
CE => '1', -- 1-bit clock enable input
|
|
D1 => '1', -- 1-bit data input (positive edge)
|
|
D2 => '0', -- 1-bit data input (negative edge)
|
|
R => '0', -- 1-bit reset input
|
|
S => '0' -- 1-bit set input
|
|
);
|
|
|
|
ssram_bufg: bufg
|
|
port map
|
|
(
|
|
o => dcm_clk1,
|
|
i => dcm_clk0
|
|
);
|
|
|
|
inst_DCM_BASE_0 : DCM_BASE
|
|
generic map (
|
|
CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
|
|
-- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
|
|
CLKFX_DIVIDE => 1, -- Can be any interger from 1 to 32
|
|
CLKFX_MULTIPLY => 4, -- Can be any integer from 2 to 32
|
|
CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature
|
|
CLKIN_PERIOD => 10.0 , -- Specify period of input clock in ns from 1.25 to 1000.00
|
|
CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift mode of NONE or FIXED
|
|
CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE or 1X
|
|
DCM_AUTOCALIBRATION => TRUE, -- DCM calibrartion circuitry TRUE/FALSE
|
|
DCM_PERFORMANCE_MODE => "MAX_SPEED", -- Can be MAX_SPEED or MAX_RANGE
|
|
DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
|
|
-- an integer from 0 to 15
|
|
DFS_FREQUENCY_MODE => "LOW", -- LOW or HIGH frequency mode for frequency synthesis
|
|
DLL_FREQUENCY_MODE => "LOW", -- LOW, HIGH, or HIGH_SER frequency mode for DLL
|
|
DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE
|
|
FACTORY_JF => X"F0F0", -- FACTORY JF Values Suggested to be set to X"F0F0"
|
|
PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 1023
|
|
STARTUP_WAIT => FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
|
|
port map (
|
|
CLK0 => dcm_clk0, -- 0 degree DCM CLK ouptput
|
|
CLK180 => open, -- 180 degree DCM CLK output
|
|
CLK270 => open, -- 270 degree DCM CLK output
|
|
CLK2X => open, -- 2X DCM CLK output
|
|
CLK2X180 => open, -- 2X, 180 degree DCM CLK out
|
|
CLK90 => open, -- 90 degree DCM CLK output
|
|
CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE)
|
|
CLKFX => open, -- DCM CLK synthesis out (M/D)
|
|
CLKFX180 => open, -- 180 degree CLK synthesis out
|
|
LOCKED => dcm_locked, -- DCM LOCK status output
|
|
CLKFB => ssram_clk_fb, -- DCM clock feedback
|
|
CLKIN => CLK_I, -- Clock input (from IBUFG, BUFG or DCM)
|
|
RST => RST_I -- DCM asynchronous reset input
|
|
);
|
|
|
|
|
|
data_valid_pipeline:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if RST_I = '1' then
|
|
vld_pipe <= (others => '0');
|
|
bsy_pipe <= (others => '0');
|
|
else
|
|
bsy_pipe <= bsy_pipe(bsy_pipe'left-1 downto 0) & (data_en);
|
|
vld_pipe <= vld_pipe(vld_pipe'left-1 downto 0) & (data_en and MRDY_I and not WE_I);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
data_out_pipeline:
|
|
process(CLK_I)
|
|
begin
|
|
if rising_edge(CLK_I) then
|
|
if RST_I = '1' then
|
|
ssram_ce_n <= '1' after topad;
|
|
ssram_adv <= '0' after topad;
|
|
ssram_mode <= '0' after topad;
|
|
ssram_zz <= '1' after topad;
|
|
drive_pipe <= (others => '0');
|
|
else
|
|
ssram_ce_n <= not data_en after topad;
|
|
ssram_adv <= '0' after topad;
|
|
ssram_mode <= '0' after topad;
|
|
ssram_zz <= '0' after topad;
|
|
ssram_bw_n <= not SEL_I after topad;
|
|
drive_pipe <= drive_pipe(drive_pipe'left-1 downto 0) & (data_en and WE_I);
|
|
data_pipe <= data_pipe(data_pipe'left-1 downto 0) & ssram_dout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
ssram_dp <= data_pipe(data_pipe'left)(data_width+parity_width-1 downto data_width) after topad when drive = '1' else (others => 'Z') after topad;
|
|
|
|
end behavior;
|