library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; entity bc_trigger is generic ( no_bcmasks : integer := 1 ); port ( clk40 : in std_logic; rst40 : in std_logic; clk_scsn : in std_logic; rst_scsn : in std_logic; scsn_addr : in std_logic_vector(11 downto 0); scsn_din : in std_logic_vector(31 downto 0); scsn_dout : out std_logic_vector(31 downto 0); scsn_we : in std_logic; scsn_req : in std_logic; scsn_ack : out std_logic; bc : in std_logic_vector(11 downto 0); trg : out std_logic_vector(no_bcmasks-1 downto 0) ); end bc_trigger; architecture behav of bc_trigger is component ram4k_w8_r1 is port ( clk : in std_logic; we : in std_logic; addrA : in std_logic_vector( 8 downto 0); addrB : in std_logic_vector(11 downto 0); dinA : in std_logic_vector( 7 downto 0); doutA : out std_logic_vector( 7 downto 0); doutB : out std_logic_vector( 0 downto 0) ); end component; subtype sm_type is std_logic_vector(1 downto 0); constant idle : sm_type := "00"; constant rd : sm_type := "01"; constant wr : sm_type := "10"; constant finish : sm_type := "11"; signal sm : sm_type; signal we : std_logic; signal din_byte : std_logic_vector(7 downto 0); signal scsn_din_byte : std_logic_vector(7 downto 0); signal scsn_dout_byte : std_logic_vector(7 downto 0); type byte_array is array(0 to no_bcmasks-1) of std_logic_vector(7 downto 0); signal dout_byte : byte_array; signal clr_addr : std_logic_vector(8 downto 0); constant clr_addr_full : std_logic_vector(clr_addr'range) := (others => '1'); signal byte_addr : std_logic_vector(8 downto 0); signal byte_we : std_logic_vector(no_bcmasks-1 downto 0); signal req_clr : std_logic; signal byte_count : std_logic_vector(1 downto 0); begin we <= scsn_we when (scsn_addr(11 downto 9) = "000") else '0'; ram_gen : for i in 0 to no_bcmasks-1 generate bram_inst : ram4k_w8_r1 port map( clk => clk40, we => byte_we(i), addrA => byte_addr, addrB => bc, dinA => din_byte, doutA => dout_byte(i), doutB(0) => trg(i) ); -- write enable to the memory byte_we(i) <= '1' when sm = wr and scsn_addr(8 downto 7) = std_logic_vector(to_unsigned(i, 2)) else '0'; end generate; scsn_dout_byte <= dout_byte(to_integer(unsigned(scsn_addr(7 downto 7)))); with req_clr select byte_addr <= scsn_addr(6 downto 0) & byte_count when '0', clr_addr when '1', (others => 'X') when others; byte_count <= clr_addr(byte_count'range); -- memory access state machine process(clk40) begin if rising_edge(clk40) then if rst40 = '1' then sm <= idle; req_clr <= '1'; clr_addr <= (others => '0'); else case sm is when idle => clr_addr <= (others => '0'); if scsn_we='1' and scsn_addr(11 downto 9) = "111" then req_clr <= '1'; elsif we = '1' or req_clr = '1' then sm <= wr; elsif scsn_req = '1' then sm <= rd; end if; when rd => if byte_count /= "11" then clr_addr <= clr_addr + 1; else sm <= finish; end if; when wr => if req_clr = '1' then if clr_addr = clr_addr_full then sm <= finish; end if; clr_addr <= clr_addr + 1; elsif byte_count /= "11" then clr_addr <= clr_addr + 1; else sm <= finish; end if; when finish => req_clr <= '0'; if scsn_req = '0' then sm <= idle; end if; when others => sm <= (others => 'X'); end case; end if; end if; end process; -- mux to the input of the memory with byte_count select scsn_din_byte <= scsn_din( 7 downto 0) when "00", scsn_din(15 downto 8) when "01", scsn_din(23 downto 16) when "10", scsn_din(31 downto 24) when "11", (others => '-') when others; -- clear the input when memory clear running with req_clr select din_byte <= scsn_din_byte when '0', (others => '0') when '1', (others => 'X') when others; -- SCSN access to RAM process (clk40) begin if rising_edge(clk40) then if rst40 = '1' then scsn_ack <= '0'; else if ((sm = rd or sm = wr) and (byte_count = "11") and (req_clr = '0') ) or (req_clr = '1') then scsn_ack <= '1'; elsif sm = idle then scsn_ack <= '0'; end if; end if; end if; end process; -- read demux for bits 0..23 process (clk40) begin if rising_edge(clk40) then if sm = rd then case byte_count is when "01" => scsn_dout( 7 downto 0) <= dout_byte(to_integer(unsigned(scsn_addr(7 downto 7)))); when "10" => scsn_dout(15 downto 8) <= dout_byte(to_integer(unsigned(scsn_addr(7 downto 7)))); when "11" => scsn_dout(23 downto 16) <= dout_byte(to_integer(unsigned(scsn_addr(7 downto 7)))); when others => NULL; end case; end if; end if; end process; -- direct routing of bits 24..31 scsn_dout(31 downto 24) <= dout_byte(to_integer(unsigned(scsn_addr(8 downto 7)))); end;