port
(
-- External
- --clk_cpu : in std_logic;
- clk_50m : in std_logic;
+ --clk_cpu : in std_logic;
+ clk_50m : in std_logic;
- cs0_xc : in std_logic;
+ cs0_xc : in std_logic;
- rd : in std_logic;
- bls : in std_logic_vector(3 downto 0);
- address : in std_logic_vector(15 downto 0);
- data : inout std_logic_vector(31 downto 0);
+ rd : in std_logic;
+ bls : in std_logic_vector(3 downto 0);
+ address : in std_logic_vector(15 downto 0);
+ data : inout std_logic_vector(31 downto 0);
irc1_a : in std_logic;
irc1_b : in std_logic;
architecture Behavioral of lx_rocon_top is
-- Reset signal
- signal reset : std_logic;
- signal neg_init : std_logic;
-
+ signal reset_s : std_logic;
+ signal neg_init_s : std_logic;
-- 100 MHz clock
- signal clk_100m : std_logic;
- signal clk_100m_fb : std_logic;
- signal clk_100m_locked : std_logic;
-
+ signal clk_100m_s : std_logic;
+ signal clk_100m_fb_s : std_logic;
+ signal clk_100m_locked_s : std_logic;
-- Peripherals on the memory bus
- signal tumbl_out : std_logic_vector(31 downto 0);
- signal tumbl_ta : std_logic;
- signal tumbl_ce : std_logic;
-
- signal irc_reg_out : std_logic_vector(31 downto 0);
- signal irc_reg_ta : std_logic;
- signal irc_reg_ce : std_logic;
-
- signal calib_out : std_logic_vector(31 downto 0);
- signal calib_ta : std_logic;
- signal calib_ce : std_logic;
-
+ signal tumbl_out_s : std_logic_vector(31 downto 0);
+ signal tumbl_ta_s : std_logic;
+ signal tumbl_ce_s : std_logic;
+ --
+ signal irc_reg_out_s : std_logic_vector(31 downto 0);
+ signal irc_reg_ta_s : std_logic;
+ signal irc_reg_ce_s : std_logic;
+ --
+ signal calib_out_s : std_logic_vector(31 downto 0);
+ signal calib_ta_s : std_logic;
+ signal calib_ce_s : std_logic;
-- Signals for external bus transmission
- signal data_in_bus : std_logic_vector(31 downto 0);
- signal data_out_bus : std_logic_vector(31 downto 0);
-
+ signal data_i_s : std_logic_vector(31 downto 0);
+ signal data_o_s : std_logic_vector(31 downto 0);
-- Signals for internal transaction
- signal last_address : std_logic_vector(15 downto 0);
- signal last_rd : std_logic;
- signal last_bls : std_logic_vector(3 downto 0);
+ signal last_address_s : std_logic_vector(15 downto 0);
+ signal last_rd_s : std_logic;
+ signal last_bls_s : std_logic_vector(3 downto 0);
-- Reading logic:
-- Broadcast rd only till ta (transaction acknowledge)
-- Data latching is synchronous - it's purpose is to
-- provide stable data for CPU on the bus on high rise
-- of trans. ack signal
- signal rd_f : std_logic;
- signal rd_d : std_logic;
-
- signal data_read : std_logic_vector(31 downto 0);
-
- signal i_ta : std_logic;
- signal i_rd : std_logic;
- signal acked : std_logic;
+ signal rd_f_s : std_logic; -- Filtered RD
+ signal rd_d_s : std_logic; -- D over RD
+ signal i_ta_s : std_logic; -- Internal bus TA (active 1)
+ signal i_rd_s : std_logic; -- Internal bus RD (active 1)
+ --
+ signal data_read_s : std_logic_vector(31 downto 0); -- Latched read data
+ --
+ signal acked_s : std_logic;
-- Writing logic:
- signal bls_f : std_logic_vector(3 downto 0);
- signal bls_d : std_logic_vector(3 downto 0);
-
- signal data_write : std_logic_vector(31 downto 0);
-
- signal i_bls : std_logic_vector(3 downto 0);
+ signal bls_f_s : std_logic_vector(3 downto 0); -- Filtered BLS
+ signal bls_d_s : std_logic_vector(3 downto 0); -- D over BLS
+ signal i_bls_s : std_logic_vector(3 downto 0); -- Internal BLS (active 1)
+ --
+ signal data_write_s : std_logic_vector(31 downto 0); -- Data broadcasted to write
begin
clk_100m_dcm_sp : DCM_SP
generic map
(
- clkdv_divide => 2.0,
- clkfx_divide => 1,
- clkfx_multiply => 2,
- clkin_divide_by_2 => false,
- clkin_period => 20.0, -- 50 MHz
- clkout_phase_shift => "NONE",
- clk_feedback => "1X",
- deskew_adjust => "SYSTEM_SYNCHRONOUS",
- dfs_frequency_mode => "LOW",
- dll_frequency_mode => "LOW",
- dss_mode => "NONE",
+ clkdv_divide => 2.0,
+ clkfx_divide => 1,
+ clkfx_multiply => 2,
+ clkin_divide_by_2 => false,
+ clkin_period => 20.0, -- 50 MHz
+ clkout_phase_shift => "NONE",
+ clk_feedback => "1X",
+ deskew_adjust => "SYSTEM_SYNCHRONOUS",
+ dfs_frequency_mode => "LOW",
+ dll_frequency_mode => "LOW",
+ dss_mode => "NONE",
duty_cycle_correction => true,
- factory_jf => X"c080",
- phase_shift => 0,
- startup_wait => false
+ factory_jf => X"c080",
+ phase_shift => 0,
+ startup_wait => false
)
port map
(
- clk0 => clk_100m_fb,
- clk180 => open,
- clk270 => open,
- clk2x => clk_100m,
- clk2x180 => open,
- clk90 => open,
- clkdv => open,
- clkfx => open,
- clkfx180 => open,
- locked => clk_100m_locked,
- psdone => open,
- status => open,
- clkfb => clk_100m_fb,
- clkin => clk_50m,
- dssen => '0',
- psclk => '0',
- psen => '0',
- psincdec => '0',
- rst => neg_init
+ clk0 => clk_100m_fb_s,
+ clk180 => open,
+ clk270 => open,
+ clk2x => clk_100m_s,
+ clk2x180 => open,
+ clk90 => open,
+ clkdv => open,
+ clkfx => open,
+ clkfx180 => open,
+ locked => clk_100m_locked_s,
+ psdone => open,
+ status => open,
+ clkfb => clk_100m_fb_s,
+ clkin => clk_50m,
+ dssen => '0',
+ psclk => '0',
+ psen => '0',
+ psincdec => '0',
+ rst => neg_init_s
);
-- IRC interconnect
memory_bus_irc: bus_irc
port map
(
- clk => clk_100m,
- reset => reset,
- address => address(3 downto 0),
- ce => irc_reg_ce,
- data_in => data_in_bus(0),
- data_out => irc_reg_out,
- rd => i_rd,
- wr => i_bls(0),
- ta => irc_reg_ta,
-
- irc1_a => irc1_a,
- irc1_b => irc1_b,
- irc1_index => irc1_index,
- irc1_mark => irc1_mark,
-
- irc2_a => irc2_a,
- irc2_b => irc2_b,
- irc2_index => irc2_index,
- irc2_mark => irc2_mark,
-
- irc3_a => irc3_a,
- irc3_b => irc3_b,
- irc3_index => irc3_index,
- irc3_mark => irc3_mark,
-
- irc4_a => irc4_a,
- irc4_b => irc4_b,
- irc4_index => irc4_index,
- irc4_mark => irc4_mark
+ clk_i => clk_100m_s,
+ reset_i => reset_s,
+ address_i => address(3 downto 0),
+ ce_i => irc_reg_ce_s,
+ data_i => data_i_s(0),
+ data_o => irc_reg_out_s,
+ rd_i => i_rd_s,
+ wr_i => i_bls_s(0),
+ ta_o => irc_reg_ta_s,
+ --
+ irc1_a_i => irc1_a,
+ irc1_b_i => irc1_b,
+ irc1_index_i => irc1_index,
+ irc1_mark_i => irc1_mark,
+ --
+ irc2_a_i => irc2_a,
+ irc2_b_i => irc2_b,
+ irc2_index_i => irc2_index,
+ irc2_mark_i => irc2_mark,
+ --
+ irc3_a_i => irc3_a,
+ irc3_b_i => irc3_b,
+ irc3_index_i => irc3_index,
+ irc3_mark_i => irc3_mark,
+ --
+ irc4_a_i => irc4_a,
+ irc4_b_i => irc4_b,
+ irc4_index_i => irc4_index,
+ irc4_mark_i => irc4_mark
);
-- Tumbl coprocessor
memory_bus_tumbl: bus_tumbl
port map
(
- clk_100m => clk_100m,
- clk_50m => clk_50m,
- reset => reset,
- ce => tumbl_ce,
- ta => tumbl_ta,
- rd => i_rd,
- bls => i_bls,
- address => address(11 downto 0),
- data_in => data_in_bus,
- data_out => tumbl_out,
-
- XMEMB_o => open,
- XMEMB_i.clken => '1',
- XMEMB_i.data => (others => '1'),
- XMEMB_i.int => '0',
- XMEMB_sel_o => open
+ clk_100m_i => clk_100m_s,
+ clk_50m_i => clk_50m,
+ reset_100m_i => reset_s,
+ ce_100m_i => tumbl_ce_s,
+ ta_100m_o => tumbl_ta_s,
+ rd_100m_i => i_rd_s,
+ bls_100m_i => i_bls_s,
+ address_100m_i => address(11 downto 0),
+ data_100m_i => data_i_s,
+ data_100m_o => tumbl_out_s,
+ --
+ XMEMB_50m_o => open,
+ XMEMB_50m_i.clken => '1',
+ XMEMB_50m_i.data => (others => '1'),
+ XMEMB_50m_i.int => '0',
+ XMEMB_sel_50m_o => open
);
-- Calibration
memory_bus_calibration: bus_calibration
port map
(
- clk => clk_100m,
- reset => reset,
- ce => calib_ce,
- address => address(1 downto 0),
- rd => i_rd,
- bls => i_bls,
- ta => calib_ta,
- data_in => data_in_bus,
- data_out => calib_out
+ clk_i => clk_100m_s,
+ reset_i => reset_s,
+ ce_i => calib_ce_s,
+ address_i => address(1 downto 0),
+ rd_i => i_rd_s,
+ bls_i => i_bls_s,
+ ta_o => calib_ta_s,
+ data_i => data_i_s,
+ data_o => calib_out_s
);
-- Filters
--bls_f <= bls when bls = bls_d else "1111";
- bls_f(0) <= bls(0) when bls(0) = bls_d(0) else '1';
- bls_f(1) <= bls(2) when bls(2) = bls_d(2) else '1';
- bls_f(2) <= bls(2) when bls(2) = bls_d(2) else '1';
- bls_f(3) <= bls(3) when bls(3) = bls_d(3) else '1';
- rd_f <= rd when rd = rd_d else '1';
+ bls_f_s(0) <= bls(0) when bls(0) = bls_d_s(0) else '1';
+ bls_f_s(1) <= bls(2) when bls(2) = bls_d_s(2) else '1';
+ bls_f_s(2) <= bls(2) when bls(2) = bls_d_s(2) else '1';
+ bls_f_s(3) <= bls(3) when bls(3) = bls_d_s(3) else '1';
+ rd_f_s <= rd when rd = rd_d_s else '1';
-- Bus update
- memory_bus_update: process(clk_100m)
+memory_bus_update:
+ process(clk_100m_s)
begin
- if clk_100m = '1' and clk_100m'event then
+ if clk_100m_s = '1' and clk_100m_s'event then
-- Set every signal to inactive state here
- irc_reg_ce <= '1';
- tumbl_ce <= '1';
- calib_ce <= '1';
- i_rd <= '1';
- i_bls <= (others => '1');
- data_in_bus <= (others => 'X');
+ irc_reg_ce_s <= '0';
+ tumbl_ce_s <= '0';
+ calib_ce_s <= '0';
+ i_rd_s <= '0';
+ i_bls_s <= (others => '0');
+ data_i_s <= (others => 'X');
-- Check if we have chip select
- if cs0_xc = '0' then
+ if reset_s = '1' then
+ acked_s <= '1';
+ i_ta_s <= '0';
+ data_read_s <= (others => '0');
+ elsif cs0_xc = '0' then
-- Memory Map (16-bit address @ 32-bit each)
-- 0x8000 - 0x800F: IRC registers
-- 0xFFFC - 0xFFFF: Calibration
- if address < "0001000000000000" then -- Tumbl
- tumbl_ce <= '0';
- i_ta <= tumbl_ta;
- data_out_bus <= tumbl_out;
- elsif address(15 downto 4) = "100000000000" then -- IRC
- irc_reg_ce <= '0';
- i_ta <= irc_reg_ta;
- data_out_bus <= irc_reg_out;
+ if address < "0001000000000000" then -- Tumbl
+ tumbl_ce_s <= '1';
+ i_ta_s <= tumbl_ta_s;
+ data_o_s <= tumbl_out_s;
+ elsif address(15 downto 4) = "100000000000" then -- IRC
+ irc_reg_ce_s <= '1';
+ i_ta_s <= irc_reg_ta_s;
+ data_o_s <= irc_reg_out_s;
elsif address(15 downto 2) = "11111111111111" then -- Calibration
- calib_ce <= '0';
- i_ta <= calib_ta;
- data_out_bus <= calib_out;
+ calib_ce_s <= '1';
+ i_ta_s <= calib_ta_s;
+ data_o_s <= calib_out_s;
end if;
-- Reading
- if rd_f = '0' then
- if last_rd = '1' or last_address /= address then
+ if rd_f_s = '0' then
+ if last_rd_s = '1' or last_address_s /= address then
-- Getting something new
-- Set internal RD to active and reset ack and latched data
- acked <= '0';
- i_rd <= '0';
+ acked_s <= '0';
+ i_rd_s <= '1';
-- Data latching - synchronous
- data_read <= (others => 'X');
- elsif i_rd = '0' and acked = '0' and i_ta = '0' then
+ data_read_s <= (others => 'X');
+ elsif i_rd_s = '1' and acked_s = '0' and i_ta_s = '1' then
-- Got acknowledge, latch data
- acked <= '1';
- data_read <= data_out_bus;
- elsif acked = '0' then
- -- Ongoing read, keep the signal low
- i_rd <= '0';
- data_read <= (others => 'X');
+ acked_s <= '1';
+ data_read_s <= data_o_s;
+ elsif acked_s = '0' then
+ -- Ongoing read, keep the signal active
+ i_rd_s <= '1';
+ data_read_s <= (others => 'X');
end if;
- last_address <= address;
+ last_address_s <= address;
else
-- Not reading, anything goes
- data_read <= (others => 'X');
+ data_read_s <= (others => 'X');
end if;
- last_rd <= rd_f;
+ last_rd_s <= rd_f_s;
- -- Writing (BLS is filtered due to bus error otherwise)
- if bls_f /= "1111" then
+ -- Writing
+ if bls_f_s /= "1111" then
- if last_bls /= bls_f or last_address /= address then
+ if last_bls_s /= bls_f_s or last_address_s /= address then
-- Broadcast BLS for once cycle to write the data
- i_bls <= bls_f;
- data_in_bus <= data_write;
+ i_bls_s <= not bls_f_s;
+ data_i_s <= data_write_s;
end if;
- last_address <= address;
+ last_address_s <= address;
end if;
- last_bls <= bls_f;
+ last_bls_s <= bls_f_s;
else
-- Set last read / bls to '1' if CS0 is not asserted
- last_rd <= '1';
- last_bls <= (others => '1');
+ last_rd_s <= '1';
+ last_bls_s <= (others => '1');
end if;
-- Filters
- bls_d <= bls;
- rd_d <= rd;
+ bls_d_s <= bls;
+ rd_d_s <= rd;
end if;
-- If RD and BLS is not high, we must keep DATA at high impedance
-- or the FPGA collides with SDRAM (damaging each other)
- memory_bus_out: process(cs0_xc, rd, data, data_read)
+memory_bus_out:
+ process(cs0_xc, rd, data, data_read_s)
begin
-- CS0 / RD / BLS are active LOW
if cs0_xc = '0' and rd = '0' then
- data <= data_read;
+ data <= data_read_s;
else
-- IMPORTANT!!!
data <= (others => 'Z');
end if;
- data_write <= data;
+ data_write_s <= data;
end process;
-- Reset
- initialization: process(init, clk_100m_locked)
+initialization:
+ process(init, clk_100m_locked_s)
begin
- neg_init <= not init;
- reset <= (not init) or (not clk_100m_locked);
+ -- TODO: Proper reset (lacks filter and propagation with ack as we use PLL)
+ neg_init_s <= not init;
+ reset_s <= (not init) or (not clk_100m_locked_s);
end process;