diff --git a/Makefile b/Makefile index 38cc038f24960f8bc73620fb479fcaf63a636a74..0d4a2ba9e9e383c1d6ee126132115163a53b4c44 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ CORES = axi_axis_reader_v1_0 \ axi_bram_reader_v1_0 \ axi_cfg_register_v1_0 \ axi_sts_register_v1_0 \ + axi_time_trig_gen_v1_0 \ axis_avgr16bits_v1_0 \ axis_avgr32bits_v1_0 \ axis_avgr_v1_0 \ diff --git a/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd b/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b87919211c45eb512ac9b8cb89cb0d9546239824 --- /dev/null +++ b/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd @@ -0,0 +1,146 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity axi_cfg_register is + generic ( + CFG_DATA_WIDTH : natural := 1024; + AXI_DATA_WIDTH : natural := 32; + AXI_ADDR_WIDTH : natural := 32 +); +port ( + -- System signals + s_axi_aclk : in std_logic; + s_axi_aresetn : in std_logic; + + -- Configuration bits + cfg_data : out std_logic_vector(CFG_DATA_WIDTH-1 downto 0); + + -- Slave side + s_axi_awaddr : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0); -- AXI4-Lite slave: Write address + s_axi_awvalid : in std_logic; -- AXI4-Lite slave: Write address valid + s_axi_awready : out std_logic; -- AXI4-Lite slave: Write address ready + s_axi_wdata : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0); -- AXI4-Lite slave: Write data + s_axi_wstrb : in std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0);-- AXI4-Lite slave: Write strobe + s_axi_wvalid : in std_logic; -- AXI4-Lite slave: Write data valid + s_axi_wready : out std_logic; -- AXI4-Lite slave: Write data ready + s_axi_bresp : out std_logic_vector(1 downto 0); -- AXI4-Lite slave: Write response + s_axi_bvalid : out std_logic; -- AXI4-Lite slave: Write response valid + s_axi_bready : in std_logic; -- AXI4-Lite slave: Write response ready + s_axi_araddr : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0); -- AXI4-Lite slave: Read address + s_axi_arvalid : in std_logic; -- AXI4-Lite slave: Read address valid + s_axi_arready : out std_logic; -- AXI4-Lite slave: Read address ready + s_axi_rdata : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0); -- AXI4-Lite slave: Read data + s_axi_rresp : out std_logic_vector(1 downto 0); -- AXI4-Lite slave: Read data response + s_axi_rvalid : out std_logic; -- AXI4-Lite slave: Read data valid + s_axi_rready : in std_logic -- AXI4-Lite slave: Read data ready +); +end axi_cfg_register; + +architecture rtl of axi_cfg_register is + +function clogb2 (value: natural) return natural is + variable temp : natural := value; + variable ret_val : natural := 1; + begin + while temp > 1 loop + ret_val := ret_val + 1; + temp := temp / 2; + end loop; + + return ret_val; + end function; + +function sel(cond: boolean; if_true, if_false: natural) return natural is + begin + if (cond = true) then + return(if_true); + else + return(if_false); + end if; + end function; + + constant ADDR_LSB : natural := clogb2(AXI_DATA_WIDTH/8 - 1); + constant CFG_SIZE : natural := CFG_DATA_WIDTH/AXI_DATA_WIDTH; + constant CFG_WIDTH : natural := sel((CFG_SIZE > 1), clogb2(CFG_SIZE-1), 1); + + signal int_bvalid_reg, int_bvalid_next: std_logic; + + signal int_rvalid_reg, int_rvalid_next: std_logic; + signal int_rdata_reg, int_rdata_next: std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + + type int_data_mux_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + signal int_data_mux: int_data_mux_t; + + signal int_data_wire : std_logic_vector(CFG_DATA_WIDTH-1 downto 0); + signal int_ce_wire : std_logic_vector(CFG_SIZE-1 downto 0); + signal int_wvalid_wire : std_logic; + type tmp_s1_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + signal tmp_s1 : tmp_s1_t;--std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + signal reset_s : std_logic; + +begin + + int_wvalid_wire <= s_axi_awvalid and s_axi_wvalid; + + WORDS: for j in 0 to CFG_SIZE-1 generate + int_data_mux(j) <= int_data_wire(j*AXI_DATA_WIDTH+AXI_DATA_WIDTH-1 downto j*AXI_DATA_WIDTH); + int_ce_wire(j) <= '1' when (int_wvalid_wire = '1') and (unsigned(s_axi_awaddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)) = j) else '0'; + BITS: for k in 0 to AXI_DATA_WIDTH-1 generate + tmp_s1(j)(k) <= int_ce_wire(j) and s_axi_wstrb(k/8); + FDRE_inst: FDRE + generic map( INIT => '0') + port map ( + Q => int_data_wire(j*AXI_DATA_WIDTH + k), + C => s_axi_aclk, + CE => tmp_s1(j)(k), + R => reset_s, + D => s_axi_wdata(k) + ); + end generate; + end generate; + + process(s_axi_aclk) + begin + if rising_edge(s_axi_aclk) then + if(s_axi_aresetn = '0') then + reset_s <= '1'; + int_bvalid_reg <= '0'; + int_rvalid_reg <= '0'; + int_rdata_reg <= (others => '0'); + else + reset_s <= '0'; + int_bvalid_reg <= int_bvalid_next; + int_rvalid_reg <= int_rvalid_next; + int_rdata_reg <= int_rdata_next; + end if; + end if; + end process; + + int_bvalid_next <= '1' when (int_wvalid_wire = '1') else + '0' when (s_axi_bready = '1') and (int_bvalid_reg = '1') else + int_bvalid_reg; + + int_rvalid_next <= '1' when (s_axi_arvalid = '1') else + '0' when (s_axi_rready = '1') and (int_rvalid_reg = '1') else + int_rvalid_reg; + + int_rdata_next <= int_data_mux(to_integer(unsigned(s_axi_araddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)))) when (s_axi_arvalid = '1') else + int_rdata_reg; + + cfg_data <= int_data_wire; + s_axi_bresp <= (others => '0'); + s_axi_rresp <= (others => '0'); + + s_axi_awready <= int_wvalid_wire; + s_axi_wready <= int_wvalid_wire; + s_axi_bvalid <= int_bvalid_reg; + s_axi_arready <= '1'; + s_axi_rdata <= int_rdata_reg; + s_axi_rvalid <= int_rvalid_reg; + +end rtl; diff --git a/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd b/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd new file mode 100644 index 0000000000000000000000000000000000000000..00c91799a7e0fe0f39693aefc709523632c16a6d --- /dev/null +++ b/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd @@ -0,0 +1,125 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axi_time_trig_gen is + generic ( + CFG_DATA_WIDTH : natural := 64; + AXI_DATA_WIDTH : natural := 32; + AXI_ADDR_WIDTH : natural := 32 + ); + port ( + -- AXI INTERFACE CFG REGISTER + s_axi_aclk : in std_logic; + s_axi_aresetn : in std_logic; + s_axi_awaddr : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0); + s_axi_awvalid : in std_logic; + s_axi_awready : out std_logic; + s_axi_wdata : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + s_axi_wstrb : in std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0); + s_axi_wvalid : in std_logic; + s_axi_wready : out std_logic; + s_axi_bresp : out std_logic_vector(1 downto 0); + s_axi_bvalid : out std_logic; + s_axi_bready : in std_logic; + s_axi_araddr : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0); + s_axi_arvalid : in std_logic; + s_axi_arready : out std_logic; + s_axi_rdata : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0); + s_axi_rresp : out std_logic_vector(1 downto 0); + s_axi_rvalid : out std_logic; + s_axi_rready : in std_logic; + + data_clk : in std_logic; + trig_o : out std_logic + ); +end axi_time_trig_gen; + +architecture rtl of axi_time_trig_gen is + + signal cntr_reg, cntr_next : std_logic_vector(CFG_DATA_WIDTH-1 downto 0); + signal trig_reg, trig_next : std_logic; + signal comp_reg, comp_next : std_logic; + signal cfg_data_s : std_logic_vector(CFG_DATA_WIDTH-1 downto 0); + signal cfg_data_s_sync : std_logic_vector(CFG_DATA_WIDTH-1 downto 0); + signal cfg_data_comp : std_logic_vector(32-1 downto 0); + signal rstn_s : std_logic; + +begin + + --AXI interface cfg register + cfg_i : entity work.axi_cfg_register + generic map( + CFG_DATA_WIDTH => CFG_DATA_WIDTH, + AXI_DATA_WIDTH => AXI_DATA_WIDTH, + AXI_ADDR_WIDTH => AXI_ADDR_WIDTH + ) + port map( + s_axi_aclk => s_axi_aclk, + s_axi_aresetn => s_axi_aresetn, + s_axi_awaddr => s_axi_awaddr, + s_axi_awvalid => s_axi_awvalid, + s_axi_awready => s_axi_awready, + s_axi_wdata => s_axi_wdata, + s_axi_wstrb => s_axi_wstrb, + s_axi_wvalid => s_axi_wvalid, + s_axi_wready => s_axi_wready, + s_axi_bresp => s_axi_bresp, + s_axi_bvalid => s_axi_bvalid, + s_axi_bready => s_axi_bready, + s_axi_araddr => s_axi_araddr, + s_axi_arvalid => s_axi_arvalid, + s_axi_arready => s_axi_arready, + s_axi_rdata => s_axi_rdata, + s_axi_rresp => s_axi_rresp, + s_axi_rvalid => s_axi_rvalid, + s_axi_rready => s_axi_rready, + cfg_data => cfg_data_s + ); + + -- synchronizer 0 from PS to PL clk -> PL + sync0_i: entity work.shift_register + generic map( + SR_WIDTH => CFG_DATA_WIDTH, + SR_DEPTH => 2 + ) + port map + ( + aclk => data_clk, + aresetn => '1', + en => '1', + data_i => cfg_data_s, + data_o => cfg_data_s_sync + ); + + rstn_s <= cfg_data_s_sync(32); + cfg_data_comp <= cfg_data_s_sync(31 downto 0); + + process(data_clk) + begin + if rising_edge(data_clk) then + if (rstn_s = '0') then + cntr_reg <= (others => '0'); + trig_reg <= '0'; + comp_reg <= '0'; + else + cntr_reg <= cntr_next; + trig_reg <= trig_next; + comp_reg <= comp_next; + end if; + end if; + end process; + + comp_next <= '0' when (unsigned(cntr_reg) = unsigned(cfg_data_comp)-1) else + '1'; + + cntr_next <= std_logic_vector(unsigned(cntr_reg) + 1) when (comp_reg = '1') else + (others => '0') when (comp_reg = '0') else --reset + cntr_reg; + + trig_next <= '1' when (unsigned(cntr_reg) = unsigned(cfg_data_comp)-1) else + '0'; + + trig_o <= trig_reg; + +end rtl; diff --git a/cores/axi_time_trig_gen_v1_0/core_config.tcl b/cores/axi_time_trig_gen_v1_0/core_config.tcl new file mode 100644 index 0000000000000000000000000000000000000000..78ba88feccef5433d5073e923283d40f6447a1fe --- /dev/null +++ b/cores/axi_time_trig_gen_v1_0/core_config.tcl @@ -0,0 +1,18 @@ +set display_name {AXI Time Trigger Generator} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.} +core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.} +core_parameter CFG_DATA_WIDTH {CFG DATA WIDTH} {Width of the configuration data.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axi] +set_property NAME S_AXI $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axi_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXI $parameter diff --git a/cores/axi_time_trig_gen_v1_0/shift_reg.vhd b/cores/axi_time_trig_gen_v1_0/shift_reg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..39f9b35e69ecab2fd2b35f8152b258c7dd3426cd --- /dev/null +++ b/cores/axi_time_trig_gen_v1_0/shift_reg.vhd @@ -0,0 +1,40 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity shift_register is + generic( + SR_WIDTH: integer := 32; + SR_DEPTH: integer := 2 + ); + port ( + aclk : in std_logic; + aresetn: in std_logic; + en : in std_logic; + data_i : in std_logic_vector(SR_WIDTH-1 downto 0); + data_o : out std_logic_vector(SR_WIDTH-1 downto 0)); +end shift_register; + +architecture rtl of shift_register is + type fifo_t is array (SR_DEPTH-1 downto 0) of std_logic_vector(SR_WIDTH-1 downto 0); + signal fifo_s: fifo_t := (others =>(others => '0')); + +begin + shift: process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + fifo_s <= (others => (others => '0')); + else + if en = '1' then + fifo_s(0) <= data_i; + for i in 0 to SR_DEPTH-2 loop + fifo_s(i+1) <= fifo_s(i); + end loop; + end if; + end if; + end if; + end process; + data_o <= fifo_s(SR_DEPTH-1); + +end rtl;