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;