library ieee;
use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
+use work.lx_rocon_pkg.all;
--- IRC bus interconnect: memory region for IRC
-
+-- IRC bus interconnect
entity bus_irc is
port
(
- clk : in std_logic;
- reset : in std_logic;
-
- -- Address (needs just last 4 bits, rest is wired to CE)
- address : in std_logic_vector(3 downto 0);
- ce : in std_logic;
-
+ clk_i : in std_logic;
+ reset_i : in std_logic;
-- Data bus
- data_in : in std_logic; -- 1 bit input
- data_out : out std_logic_vector(31 downto 0);
-
- -- Bus signals
- rd : in std_logic;
- ta : out std_logic;
- wr : in std_logic;
-
+ address_i : in std_logic_vector(4 downto 0);
+ ce_i : in std_logic;
+ data_i : in std_logic_vector(31 downto 0);
+ data_o : out std_logic_vector(31 downto 0);
+ --
+ bls_i : in std_logic_vector(3 downto 0);
-- Signals for IRC
- irc1_a : in std_logic;
- irc1_b : in std_logic;
- irc1_index : in std_logic;
- irc1_mark : in std_logic;
-
- irc2_a : in std_logic;
- irc2_b : in std_logic;
- irc2_index : in std_logic;
- irc2_mark : in std_logic;
-
- irc3_a : in std_logic;
- irc3_b : in std_logic;
- irc3_index : in std_logic;
- irc3_mark : in std_logic;
-
- irc4_a : in std_logic;
- irc4_b : in std_logic;
- irc4_index : in std_logic;
- irc4_mark : in std_logic
-
+ irc_i : in IRC_INPUT_Array_Type(7 downto 0)
);
end bus_irc;
architecture Behavioral of bus_irc is
- -- Multiplexer signals
- signal irc1_out : std_logic_vector(31 downto 0);
- signal irc1_ta : std_logic;
- signal irc1_ce : std_logic_vector(1 downto 0);
-
- signal irc2_out : std_logic_vector(31 downto 0);
- signal irc2_ta : std_logic;
- signal irc2_ce : std_logic_vector(1 downto 0);
-
- signal irc3_out : std_logic_vector(31 downto 0);
- signal irc3_ta : std_logic;
- signal irc3_ce : std_logic_vector(1 downto 0);
-
- signal irc4_out : std_logic_vector(31 downto 0);
- signal irc4_ta : std_logic;
- signal irc4_ce : std_logic_vector(1 downto 0);
-
- -- IRC register
- component irc_register
- port
- (
- clk : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
- index0 : in std_logic;
- mark0 : in std_logic;
- data_in : in std_logic;
- data_out : out std_logic_vector(31 downto 0);
- ce : in std_logic_vector(1 downto 0);
- rd : in std_logic;
- ta : out std_logic;
- wr : in std_logic
- );
- end component;
+ constant num_irc_c : positive := 8;
+
+ signal irc_o_s : IRC_OUTPUT_Array_Type(num_irc_c-1 downto 0);
+ signal irc_count_s : IRC_COUNT_OUTPUT_Array_Type((num_irc_c-1) downto 0);
+
+ signal reset_index_event_s : std_logic_vector(num_irc_c-1 downto 0);
+ signal reset_index_event2_s : std_logic_vector(num_irc_c-1 downto 0);
+ signal reset_ab_error_s : std_logic_vector(num_irc_c-1 downto 0);
+ signal state_o_s : std_logic_vector(3 downto 0);
+ signal state_o_r : std_logic_vector(3 downto 0);
+ --
+ signal irc_en_s : std_logic;
+ signal irc_bls_s : std_logic_vector(3 downto 0);
+ signal irc_addr_s : std_logic_vector(3 downto 0);
+ signal irc_data_s : std_logic_vector(31 downto 0);
+ signal irc_out_s : std_logic;
+ signal irc_out_r : std_logic;
+ --
+ signal reset_reg_s : std_logic;
+ signal reset_reg_r : std_logic;
+ signal reset_reg_wr_s : std_logic;
+ --
+ signal reset_s : std_logic;
+ signal ce_r : std_logic;
begin
- -- IRC for first axis
- irc1: irc_register
- port map
+irc_generate: for i in 0 to num_irc_c-1 generate
+ irc : irc_reader
+ port map
+ (
+ clk_i => clk_i,
+ reset_i => reset_s,
+ irc_i => irc_i(i),
+ reset_index_event_i => reset_index_event_s(i),
+ reset_index_event2_i => reset_index_event2_s(i),
+ reset_ab_error_i => reset_ab_error_s(i),
+ irc_o => irc_o_s(i)
+ );
+
+ irc_count_s(i) <= irc_o_s(i).count;
+ end generate;
+
+irc_proc : irc_proc_main
+ generic map
(
- clk => clk,
- reset => reset,
- a0 => irc1_a,
- b0 => irc1_b,
- index0 => irc1_index,
- mark0 => irc1_mark,
- data_in => data_in,
- data_out => irc1_out,
- ce => irc1_ce,
- rd => rd,
- ta => irc1_ta,
- wr => wr
- );
-
- -- IRC for second axis
- irc2: irc_register
+ num_irc_g => num_irc_c
+ )
port map
(
- clk => clk,
- reset => reset,
- a0 => irc2_a,
- b0 => irc2_b,
- index0 => irc2_index,
- mark0 => irc2_mark,
- data_in => data_in,
- data_out => irc2_out,
- ce => irc2_ce,
- rd => rd,
- ta => irc2_ta,
- wr => wr
+ clk_i => clk_i,
+ reset_i => reset_s,
+ -- IRC
+ irc_i => irc_count_s,
+ irc_index_reset_o => reset_index_event_s,
+ -- BRAM
+ mem_clk_i => clk_i,
+ mem_en_i => irc_en_s,
+ mem_we_i => irc_bls_s,
+ mem_addr_i => irc_addr_s,
+ mem_data_i => data_i,
+ mem_data_o => irc_data_s
);
- -- IRC for thrid axis
- irc3: irc_register
- port map
- (
- clk => clk,
- reset => reset,
- a0 => irc3_a,
- b0 => irc3_b,
- index0 => irc3_index,
- mark0 => irc3_mark,
- data_in => data_in,
- data_out => irc3_out,
- ce => irc3_ce,
- rd => rd,
- ta => irc3_ta,
- wr => wr
- );
-
- -- IRC for fourth axis
- irc4: irc_register
- port map
- (
- clk => clk,
- reset => reset,
- a0 => irc4_a,
- b0 => irc4_b,
- index0 => irc4_index,
- mark0 => irc4_mark,
- data_in => data_in,
- data_out => irc4_out,
- ce => irc4_ce,
- rd => rd,
- ta => irc4_ta,
- wr => wr
- );
+ reset_s <= reset_reg_r or reset_i;
- -- Bus update
- memory_bus_update: process(ce, address, irc1_out, irc1_ta, irc2_out, irc2_ta,
- irc3_out, irc3_ta, irc4_out, irc4_ta)
+wire_in:
+ process(ce_i, ce_r, reset_reg_r, bls_i, address_i, irc_data_s, data_i, irc_o_s)
begin
- -- Reset signals
- irc1_ce <= "11";
- irc2_ce <= "11";
- irc3_ce <= "11";
- irc4_ce <= "11";
-
- ta <= '1';
- data_out <= (others => 'X');
+ -- init values
+ irc_en_s <= '0';
+ irc_out_s <= '0';
+ irc_bls_s <= (others => '0');
+ irc_addr_s <= (others => '0');
+ reset_ab_error_s <= (others => '0');
+ reset_index_event2_s <= (others => '0');
+ state_o_s <= (others => '0');
+ reset_reg_s <= '0';
+ reset_reg_wr_s <= '0';
+
+ -- Incoming bus request
+ if ce_i = '1' then
+ -- Mapping:
+ -- 0 & axis & irc / index - (all read from bram) (R/W)
+ -- 1 & axis & 0 - status register (R/W)
+ -- 1 & 000 & 1 - reset
+ if address_i(4) = '0' then
+
+ irc_addr_s <= address_i(3 downto 0);
+ irc_en_s <= '1';
+ irc_bls_s <= bls_i;
+ irc_out_s <= '1';
+
+ -- Maybe these would be better to latch in ce_i cycle,
+ -- and then just pass them
+ elsif address_i(0) = '0' then
+
+ state_o_s(0) <= irc_o_s(to_integer(unsigned(address_i(3 downto 1)))).state.mark;
+ state_o_s(1) <= irc_o_s(to_integer(unsigned(address_i(3 downto 1)))).state.ab_error;
+ state_o_s(2) <= irc_o_s(to_integer(unsigned(address_i(3 downto 1)))).state.index_event;
+ state_o_s(3) <= irc_o_s(to_integer(unsigned(address_i(3 downto 1)))).state.index;
+
+ if bls_i(0) = '1' then
+ if data_i(1) = '1' then
+ reset_ab_error_s(to_integer(unsigned(address_i(3 downto 1)))) <= '1';
+ end if;
+ if data_i(2) = '1' then
+ reset_index_event2_s(to_integer(unsigned(address_i(3 downto 1)))) <= '1';
+ end if;
+ end if;
+ elsif address_i = "10001" then
+
+ if bls_i(0) = '1' then
+ reset_reg_s <= data_i(0);
+ reset_reg_wr_s <= '1';
+ else
+ -- Ugh, hack :-)
+ state_o_s(0) <= reset_reg_r;
+ state_o_s(3 downto 1) <= (others => '0');
+ end if;
+
+ end if;
- if ce = '0' then
-
- -- We have 4-bit address, and IRC module has 3 registers
- -- Higher bits choose which IRC module, lower bits are for registers of the module
- case address(3 downto 2) is
- when "00" =>
- irc1_ce <= address(1 downto 0);
- data_out <= irc1_out;
- ta <= irc1_ta;
+ end if;
+ end process;
- when "01" =>
- irc2_ce <= address(1 downto 0);
- data_out <= irc2_out;
- ta <= irc2_ta;
+wire_out:
+ process(ce_r, irc_data_s, irc_out_r, state_o_r)
+ begin
- when "10" =>
- irc3_ce <= address(1 downto 0);
- data_out <= irc3_out;
- ta <= irc3_ta;
+ data_o <= (others => '0');
- when "11" =>
- irc4_ce <= address(1 downto 0);
- data_out <= irc4_out;
- ta <= irc4_ta;
+ if ce_r = '1' then
- when others =>
- data_out <= (others => 'X');
+ if irc_out_r = '1' then
+ data_o <= irc_data_s;
+ else
+ data_o(3 downto 0) <= state_o_r;
+ end if;
- end case;
+ end if;
+ end process;
+update:
+ process
+ begin
+ wait until clk_i'event and clk_i= '1';
+ ce_r <= ce_i;
+ irc_out_r <= irc_out_s;
+ state_o_r <= state_o_s;
+
+ if reset_i = '1' then
+ reset_reg_r <= '1';
+ elsif reset_reg_wr_s = '1' then
+ reset_reg_r <= reset_reg_s;
end if;
end process;