library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library unisim; use unisim.vcomponents.all; entity ram_cnt is generic ( no : integer := 128; width : integer := 64; width_fast : integer := 8; constant width_addr : integer := 7 ); port ( clk40 : in std_logic; rst40 : in std_logic; capture : in std_logic; clear : in std_logic; inputs : in std_logic_vector(no-1 downto 0); input_mask : in std_logic_vector(no-1 downto 0); scsn_addr : in std_logic_vector(15 downto 0); scsn_dout : out std_logic_vector(31 downto 0); scsn_req : in std_logic; scsn_ack : out std_logic ); end ram_cnt; architecture default of ram_cnt is signal capturing : std_logic; -- capturing is running signal clearing : std_logic; -- clearing is running signal addr : std_logic_vector(width_addr-1 downto 0); -- RAM address -- to read from signal addr_r : std_logic_vector(width_addr-1 downto 0); signal addr_rr : std_logic_vector(width_addr-1 downto 0); signal addr_ram : std_logic_vector(width_addr-1 downto 0); -- RAM addr ??? signal addr_next : std_logic_vector(width_addr-1 downto 0); signal ram_addr : std_logic_vector(width_addr-1 downto 0); type cnt_array is array(no-1 downto 0) of std_logic_vector(width_fast-1 downto 0); signal cnt_fast : cnt_array; -- fast counters signal cnt_fast_r : cnt_array; signal cnt_curr : std_logic_vector(63 downto 0); -- value read from RAM signal cnt_new : std_logic_vector(63 downto 0); -- value to be written -- to RAM signal cnt_bak : std_logic_vector(63 downto 0); -- value for capturing signal cnt_hi : std_logic_vector(31 downto 0); signal cnt_lo : std_logic_vector(31 downto 0); signal cnt_hi_capt : std_logic_vector(31 downto 0); signal cnt_lo_capt : std_logic_vector(31 downto 0); signal cnt_run : std_logic_vector(63 downto 0); signal inp : std_logic_vector(no-1 downto 0); signal ram_we : std_logic; signal ram_cnt : std_logic_vector(7 downto 0); signal req : std_logic; signal req_addr : std_logic_vector(15 downto 0); signal req_ack : std_logic; signal req_ack_r : std_logic; signal req_ack_run : std_logic; signal req_ack_capt : std_logic; begin -- -- input masking inp <= inputs and input_mask; -- -- I/O mapping scsn_ack <= req_ack_r; -- -- fast counters gen_cnt_fast : for i in 0 to no-1 generate process (clk40) begin if rst40 = '1' or clear = '1' then cnt_fast(i) <= (others => '0'); cnt_fast_r(i) <= (others => '0'); elsif rising_edge(clk40) then -- fast counting cnt_fast(i) <= cnt_fast(i) + inp(i); -- capture fast counters for synchronous readout if capture = '1' then cnt_fast_r(i) <= cnt_fast(i); end if; -- reset slowly counted bit if addr_r = i and cnt_fast(i)(width_fast-1) = '1' then cnt_fast(i)(width_fast-1) <= '0'; end if; end if; end process; end generate; -- -- slow counters process (clk40) begin if rst40 = '1' then cnt_new <= (others => '0'); cnt_bak <= (others => '0'); elsif rising_edge(clk40) then if clearing = '1' then cnt_new <= conv_std_logic_vector(0, cnt_new'length) + cnt_fast(conv_integer(addr_r))(width_fast-1); else cnt_new <= cnt_curr + cnt_fast(conv_integer(addr_r))(width_fast-1); end if; if capturing = '1' then cnt_bak <= (cnt_curr(63-7 downto 0) + cnt_fast_r(conv_integer(addr_r))(7)) & cnt_fast_r(conv_integer(addr_r))(6 downto 0); end if; end if; end process; -- -- address counting process (clk40) begin if rst40 = '1' then addr <= (others => '0'); addr_next <= (others => '0'); addr_r <= (others => '0'); addr_ram <= (others => '0'); ram_cnt <= (others => '0'); elsif rising_edge(clk40) then addr <= addr + '1'; addr_r <= addr; addr_rr <= addr_r; addr_next <= addr + x"2"; if addr_ram < conv_std_logic_vector(no-3, addr_ram'length) then addr_ram <= addr_ram + '1'; else addr_ram <= (others => '0'); end if; if capture = '1' or clear = '1' then capturing <= capture; clearing <= clear; ram_cnt <= (others => '0'); elsif ram_cnt /= conv_std_logic_vector(no-1, ram_cnt'length) then ram_cnt <= ram_cnt + '1'; else capturing <= '0'; clearing <= '0'; end if; end if; end process; -- -- memory reading process (clk40) begin if rst40 = '1' then ram_we <= '0'; elsif rising_edge(clk40) then ram_we <= '1'; req_ack_run <= '0'; if scsn_req = '1' then req <= '1'; req_addr <= scsn_addr; end if; if req = '1' and req_addr(width_addr-1 downto 0) = addr_r then cnt_run <= (cnt_curr(63-7 downto 0) + cnt_fast(conv_integer(addr_r))(7)) & cnt_fast(conv_integer(req_addr(width_addr-1 downto 0)))(6 downto 0); req_ack_run <= '1'; req <= '0'; end if; end if; end process; cnt_lo <= cnt_run(31 downto 0) when scsn_addr(11) = '0' else cnt_lo_capt; cnt_hi <= cnt_run(63 downto 32) when scsn_addr(11) = '0' else cnt_hi_capt; -- -- SCSN readout process (clk40) begin if rst40 = '1' then req_ack_r <= '0'; scsn_dout <= (others => '0'); elsif rising_edge(clk40) then if scsn_addr(10) = '0' then scsn_dout <= cnt_lo; else scsn_dout <= cnt_hi; end if; if scsn_addr(11) = '1' then req_ack <= req_ack_capt; else req_ack <= req_ack_run; end if; req_ack_r <= req_ack; end if; end process; -- -- BRAM instance bram_inst : RAMB16_S36_S36 generic map ( WRITE_MODE_A => "READ_FIRST", WRITE_MODE_B => "READ_FIRST" ) port map ( -- port A : lower bits ADDRA(8 downto 7) => "00", ADDRA(6 downto 0) => addr_ram, DIA => cnt_new(31 downto 0), DIPA => (others => '1'), DOA => cnt_curr(31 downto 0), DOPA => open, WEA => ram_we, ENA => '1', SSRA => rst40, CLKA => clk40, -- port B : upper bits ADDRB(8 downto 7) => "01", ADDRB(6 downto 0) => addr_ram, DIB => cnt_new(63 downto 32), DIPB => (others => '1'), DOB => cnt_curr(63 downto 32), DOPB => open, WEB => ram_we, ENB => '1', SSRB => rst40, CLKB => clk40 ); -- -- BRAM for capturing ram_addr <= addr_rr when capturing = '1' else scsn_addr(ram_addr'range); req_ack_capt <= scsn_req when capturing = '0' else '0'; bram_inst_readout: RAMB16_S36_S36 generic map ( WRITE_MODE_A => "READ_FIRST", WRITE_MODE_B => "READ_FIRST" ) port map ( -- port A : lower bits ADDRA(8 downto 7) => "00", ADDRA(6 downto 0) => ram_addr, DIA => cnt_bak(31 downto 0), DIPA => (others => '1'), DOA => cnt_lo_capt, DOPA => open, WEA => capturing, ENA => '1', SSRA => rst40, CLKA => clk40, -- port B : upper bits ADDRB(8 downto 7) => "01", ADDRB(6 downto 0) => ram_addr, DIB => cnt_bak(63 downto 32), DIPB => (others => '1'), DOB => cnt_hi_capt, DOPB => open, WEB => capturing, ENB => '1', SSRB => rst40, CLKB => clk40 ); end default;