From 0f8edafdace53be9d558ae8eb6afba6d029fed1a Mon Sep 17 00:00:00 2001 From: lharnaldi <lharnaldi@gmail.com> Date: Fri, 5 Aug 2022 09:52:24 -0300 Subject: [PATCH] Agrego todos los cores necesarios para trabajar con LAGO --- Makefile | 3 + .../asym_ram_sdp_write_wider.vhd | 110 ++++ cores/axis_avgr16bits_v1_0/avg_ntoone.vhd | 253 +++++++++ cores/axis_avgr16bits_v1_0/avg_scope.vhd | 362 +++++++++++++ cores/axis_avgr16bits_v1_0/axis_averager.vhd | 312 +++++++++++ .../axis_avgr16bits_v1_0/axis_signal_mux.vhd | 43 ++ .../axis_signal_selector.vhd | 48 ++ cores/axis_avgr16bits_v1_0/bram_reader.vhd | 150 ++++++ cores/axis_avgr16bits_v1_0/core_config.tcl | 29 + cores/axis_avgr16bits_v1_0/edge_det.vhd | 58 ++ cores/axis_avgr16bits_v1_0/n_sync.vhd | 46 ++ cores/axis_avgr16bits_v1_0/sync.vhd | 43 ++ cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd | 86 +++ cores/axis_avgr32bits_v1_0/avg_ntoone.vhd | 255 +++++++++ cores/axis_avgr32bits_v1_0/avg_scope.vhd | 318 +++++++++++ cores/axis_avgr32bits_v1_0/axis_averager.vhd | 311 +++++++++++ .../axis_avgr32bits_v1_0/axis_signal_mux.vhd | 43 ++ .../axis_signal_selector.vhd | 48 ++ cores/axis_avgr32bits_v1_0/bram_reader.vhd | 184 +++++++ cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd | 149 +++++ cores/axis_avgr32bits_v1_0/core_config.tcl | 29 + cores/axis_avgr32bits_v1_0/edge_det.vhd | 58 ++ cores/axis_avgr32bits_v1_0/n_sync.vhd | 46 ++ .../old_stuffs/avg_ntoone.vhd | 256 +++++++++ .../old_stuffs/avg_scope.vhd | 365 +++++++++++++ .../old_stuffs/bram_reader.vhd | 150 ++++++ cores/axis_avgr32bits_v1_0/sync.vhd | 43 ++ cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd | 86 +++ cores/axis_avgr_v1_0/asym_ram_tdp.vhd | 115 ++++ cores/axis_avgr_v1_0/averager.vhd | 330 ++++++++++++ cores/axis_avgr_v1_0/averager.vhd_bkp | 330 ++++++++++++ cores/axis_avgr_v1_0/axis_averager.vhd | 227 ++++++++ cores/axis_avgr_v1_0/axis_bram_reader.vhd | 147 +++++ cores/axis_avgr_v1_0/axis_fifo.vhd | 124 +++++ cores/axis_avgr_v1_0/core_config.tcl | 36 ++ cores/axis_avgr_v1_0/fifo_async_ctrl.vhd | 81 +++ cores/axis_avgr_v1_0/fifo_read.vhd | 62 +++ cores/axis_avgr_v1_0/fifo_write.vhd | 62 +++ cores/axis_avgr_v1_0/n_sync.vhd | 41 ++ cores/axis_avgr_v1_0/sync.vhd | 39 ++ cores/axis_avgr_v1_0/tdp_bram.vhd | 60 +++ cores/axis_counter_v1_0/axis_counter.vhd | 61 +++ cores/axis_counter_v1_0/core_config.tcl | 17 + .../axis_dc_removal_v1_0/axis_dc_removal.vhd | 94 ++++ cores/axis_dc_removal_v1_0/core_config.tcl | 21 + cores/axis_dc_removal_v1_0/dc_removal.vhd | 92 ++++ cores/axis_fifo_v1_0/axis_fifo.vhd | 124 +++++ cores/axis_fifo_v1_0/core_config.tcl | 26 + cores/axis_fifo_v1_0/dp_bram.vhd | 60 +++ cores/axis_fifo_v1_0/fifo_async_ctrl.vhd | 81 +++ cores/axis_fifo_v1_0/fifo_read.vhd | 62 +++ cores/axis_fifo_v1_0/fifo_write.vhd | 62 +++ cores/axis_fifo_v1_0/n_sync.vhd | 41 ++ cores/axis_generator_v1_0/axis_generator.vhd | 131 +++++ cores/axis_generator_v1_0/core_config.tcl | 20 + .../axis_gpio_reader_i.vhd | 52 ++ cores/axis_gpio_reader_i_v1_0/core_config.tcl | 16 + .../axis_gpio_reader.vhd | 54 ++ cores/axis_gpio_reader_v1_0/core_config.tcl | 16 + cores/axis_histogram_v1_0/axis_histogram.vhd | 124 +++++ cores/axis_histogram_v1_0/core_config.tcl | 37 ++ cores/axis_histogram_v1_1/axis_histogram.vhd | 141 +++++ cores/axis_histogram_v1_1/core_config.tcl | 37 ++ .../axis_lago_trigger.vhd | 417 ++++++++++++++ .../axis_lago_trigger_v1_0.vhd | 417 ++++++++++++++ cores/axis_lago_trigger_v1_0/core_config.tcl | 25 + .../axis_lago_trigger.vhd | 413 ++++++++++++++ .../axis_lago_trigger_v1_1.vhd | 413 ++++++++++++++ cores/axis_lago_trigger_v1_1/core_config.tcl | 25 + .../axis_lago_trigger_v1_2.vhd | 472 ++++++++++++++++ cores/axis_lago_trigger_v1_2/core_config.tcl | 25 + .../axis_lago_trigger_v1_3.vhd | 509 ++++++++++++++++++ cores/axis_lago_trigger_v1_3/core_config.tcl | 25 + .../axis_packetizer_v1_0/axis_packetizer.vhd | 83 +++ cores/axis_packetizer_v1_0/core_config.tcl | 22 + cores/axis_rp_dac_v1_0/axis_rp_dac.vhd | 80 +++ cores/axis_rp_dac_v1_0/core_config.tcl | 17 + cores/axis_rp_dac_v2_0/axis_rp_dac.vhd | 81 +++ cores/axis_rp_dac_v2_0/core_config.tcl | 17 + cores/axis_validator_v1_0/axis_validator.vhd | 35 ++ cores/axis_validator_v1_0/core_config.tcl | 20 + cores/axis_variable_v1_0/axis_variable.vhd | 51 ++ cores/axis_variable_v1_0/core_config.tcl | 16 + .../axis_zero_crossing_det.vhd | 99 ++++ .../core_config.tcl | 17 + cores/axis_zeroer_v1_0/axis_zeroer.vhd | 34 ++ cores/axis_zeroer_v1_0/core_config.tcl | 20 + cores/bram_counter_v1_0/bram_counter.vhd | 77 +++ cores/bram_counter_v1_0/core_config.tcl | 29 + cores/bram_selector_v1_0/bram_selector.vhd | 69 +++ cores/bram_selector_v1_0/core_config.tcl | 66 +++ cores/dna_reader_v1_0/core_config.tcl | 6 + cores/dna_reader_v1_0/dna_reader.vhd | 81 +++ cores/int_counter_v1_0/core_config.tcl | 7 + cores/int_counter_v1_0/int_counter.vhd | 38 ++ cores/port_selector_v1_0/core_config.tcl | 8 + cores/port_selector_v1_0/port_selector.vhd | 30 ++ cores/ramp_gen_v1_0/core_config.tcl | 10 + cores/ramp_gen_v1_0/ramp_gen.vhd | 83 +++ cores/selector_v1_0/core_config.tcl | 7 + cores/selector_v1_0/selector.vhd | 27 + 101 files changed, 10778 insertions(+) create mode 100644 cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd create mode 100644 cores/axis_avgr16bits_v1_0/avg_ntoone.vhd create mode 100644 cores/axis_avgr16bits_v1_0/avg_scope.vhd create mode 100644 cores/axis_avgr16bits_v1_0/axis_averager.vhd create mode 100644 cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd create mode 100644 cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd create mode 100644 cores/axis_avgr16bits_v1_0/bram_reader.vhd create mode 100644 cores/axis_avgr16bits_v1_0/core_config.tcl create mode 100644 cores/axis_avgr16bits_v1_0/edge_det.vhd create mode 100644 cores/axis_avgr16bits_v1_0/n_sync.vhd create mode 100644 cores/axis_avgr16bits_v1_0/sync.vhd create mode 100644 cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd create mode 100644 cores/axis_avgr32bits_v1_0/avg_ntoone.vhd create mode 100644 cores/axis_avgr32bits_v1_0/avg_scope.vhd create mode 100644 cores/axis_avgr32bits_v1_0/axis_averager.vhd create mode 100644 cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd create mode 100644 cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd create mode 100644 cores/axis_avgr32bits_v1_0/bram_reader.vhd create mode 100644 cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd create mode 100644 cores/axis_avgr32bits_v1_0/core_config.tcl create mode 100644 cores/axis_avgr32bits_v1_0/edge_det.vhd create mode 100644 cores/axis_avgr32bits_v1_0/n_sync.vhd create mode 100644 cores/axis_avgr32bits_v1_0/old_stuffs/avg_ntoone.vhd create mode 100644 cores/axis_avgr32bits_v1_0/old_stuffs/avg_scope.vhd create mode 100644 cores/axis_avgr32bits_v1_0/old_stuffs/bram_reader.vhd create mode 100644 cores/axis_avgr32bits_v1_0/sync.vhd create mode 100644 cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd create mode 100644 cores/axis_avgr_v1_0/asym_ram_tdp.vhd create mode 100644 cores/axis_avgr_v1_0/averager.vhd create mode 100644 cores/axis_avgr_v1_0/averager.vhd_bkp create mode 100644 cores/axis_avgr_v1_0/axis_averager.vhd create mode 100644 cores/axis_avgr_v1_0/axis_bram_reader.vhd create mode 100644 cores/axis_avgr_v1_0/axis_fifo.vhd create mode 100644 cores/axis_avgr_v1_0/core_config.tcl create mode 100644 cores/axis_avgr_v1_0/fifo_async_ctrl.vhd create mode 100644 cores/axis_avgr_v1_0/fifo_read.vhd create mode 100644 cores/axis_avgr_v1_0/fifo_write.vhd create mode 100644 cores/axis_avgr_v1_0/n_sync.vhd create mode 100644 cores/axis_avgr_v1_0/sync.vhd create mode 100644 cores/axis_avgr_v1_0/tdp_bram.vhd create mode 100644 cores/axis_counter_v1_0/axis_counter.vhd create mode 100644 cores/axis_counter_v1_0/core_config.tcl create mode 100644 cores/axis_dc_removal_v1_0/axis_dc_removal.vhd create mode 100644 cores/axis_dc_removal_v1_0/core_config.tcl create mode 100644 cores/axis_dc_removal_v1_0/dc_removal.vhd create mode 100644 cores/axis_fifo_v1_0/axis_fifo.vhd create mode 100644 cores/axis_fifo_v1_0/core_config.tcl create mode 100644 cores/axis_fifo_v1_0/dp_bram.vhd create mode 100644 cores/axis_fifo_v1_0/fifo_async_ctrl.vhd create mode 100644 cores/axis_fifo_v1_0/fifo_read.vhd create mode 100644 cores/axis_fifo_v1_0/fifo_write.vhd create mode 100644 cores/axis_fifo_v1_0/n_sync.vhd create mode 100644 cores/axis_generator_v1_0/axis_generator.vhd create mode 100644 cores/axis_generator_v1_0/core_config.tcl create mode 100644 cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd create mode 100644 cores/axis_gpio_reader_i_v1_0/core_config.tcl create mode 100644 cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd create mode 100644 cores/axis_gpio_reader_v1_0/core_config.tcl create mode 100644 cores/axis_histogram_v1_0/axis_histogram.vhd create mode 100644 cores/axis_histogram_v1_0/core_config.tcl create mode 100644 cores/axis_histogram_v1_1/axis_histogram.vhd create mode 100644 cores/axis_histogram_v1_1/core_config.tcl create mode 100644 cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd create mode 100644 cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd create mode 100644 cores/axis_lago_trigger_v1_0/core_config.tcl create mode 100644 cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd create mode 100644 cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd create mode 100644 cores/axis_lago_trigger_v1_1/core_config.tcl create mode 100644 cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd create mode 100644 cores/axis_lago_trigger_v1_2/core_config.tcl create mode 100644 cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd create mode 100644 cores/axis_lago_trigger_v1_3/core_config.tcl create mode 100644 cores/axis_packetizer_v1_0/axis_packetizer.vhd create mode 100644 cores/axis_packetizer_v1_0/core_config.tcl create mode 100644 cores/axis_rp_dac_v1_0/axis_rp_dac.vhd create mode 100644 cores/axis_rp_dac_v1_0/core_config.tcl create mode 100644 cores/axis_rp_dac_v2_0/axis_rp_dac.vhd create mode 100644 cores/axis_rp_dac_v2_0/core_config.tcl create mode 100644 cores/axis_validator_v1_0/axis_validator.vhd create mode 100644 cores/axis_validator_v1_0/core_config.tcl create mode 100644 cores/axis_variable_v1_0/axis_variable.vhd create mode 100644 cores/axis_variable_v1_0/core_config.tcl create mode 100644 cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd create mode 100644 cores/axis_zero_crossing_det_v1_0/core_config.tcl create mode 100644 cores/axis_zeroer_v1_0/axis_zeroer.vhd create mode 100644 cores/axis_zeroer_v1_0/core_config.tcl create mode 100644 cores/bram_counter_v1_0/bram_counter.vhd create mode 100644 cores/bram_counter_v1_0/core_config.tcl create mode 100644 cores/bram_selector_v1_0/bram_selector.vhd create mode 100644 cores/bram_selector_v1_0/core_config.tcl create mode 100644 cores/dna_reader_v1_0/core_config.tcl create mode 100644 cores/dna_reader_v1_0/dna_reader.vhd create mode 100644 cores/int_counter_v1_0/core_config.tcl create mode 100644 cores/int_counter_v1_0/int_counter.vhd create mode 100644 cores/port_selector_v1_0/core_config.tcl create mode 100644 cores/port_selector_v1_0/port_selector.vhd create mode 100644 cores/ramp_gen_v1_0/core_config.tcl create mode 100644 cores/ramp_gen_v1_0/ramp_gen.vhd create mode 100644 cores/selector_v1_0/core_config.tcl create mode 100644 cores/selector_v1_0/selector.vhd diff --git a/Makefile b/Makefile index a9a1e50..0695bc9 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ CORES = axi_axis_reader_v1_0 \ axi_bram_reader_v1_0 \ axi_cfg_register_v1_0 \ axi_sts_register_v1_0 \ + axis_avgr16bits_v1_0 \ + axis_avgr32bits_v1_0 \ + axis_avgr_v1_0 \ axis_bram_reader_v1_0 \ axis_bram_writer_v1_0 \ axis_constant_v1_0 \ diff --git a/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd b/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd new file mode 100644 index 0000000..9292f4d --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd @@ -0,0 +1,110 @@ +-- Asymmetric port RAM +-- Write Wider than Read +-- modified from asym_ram_sdp_write_wider.vhd + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity asym_ram_sdp_write_wider is + generic( + WIDTHA : integer := 4; + SIZEA : integer := 1024; + ADDRWIDTHA : integer := 10; + WIDTHB : integer := 16; + SIZEB : integer := 256; + ADDRWIDTHB : integer := 8 + ); + + port( + clkA : in std_logic; + rstA : in std_logic; + enA : in std_logic; + addrA : in std_logic_vector(ADDRWIDTHA - 1 downto 0); + doA : out std_logic_vector(WIDTHA - 1 downto 0); + clkB : in std_logic; + --rstB : in std_logic; + --enB : in std_logic; + weB : in std_logic; + addrB : in std_logic_vector(ADDRWIDTHB - 1 downto 0); + diB : in std_logic_vector(WIDTHB - 1 downto 0) + ); + +end asym_ram_sdp_write_wider; + +architecture behavioral of asym_ram_sdp_write_wider is + function max(L, R : INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + function min(L, R : INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + function log2(val : INTEGER) return natural is + variable res : natural; + begin + for i in 0 to 31 loop + if (val <= (2 ** i)) then + res := i; + exit; + end if; + end loop; + return res; + end function Log2; + + constant minWIDTH : integer := min(WIDTHA, WIDTHB); + constant maxWIDTH : integer := max(WIDTHA, WIDTHB); + constant maxSIZE : integer := max(SIZEA, SIZEB); + constant RATIO : integer := maxWIDTH / minWIDTH; + + -- An asymmetric RAM is modeled in a similar way as a symmetric RAM, with an + -- array of array object. Its aspect ratio corresponds to the port with the + -- lower data width (larger depth) + type ramType is array (0 to maxSIZE - 1) of std_logic_vector(minWIDTH - 1 downto 0); + + signal my_ram : ramType := (others => (others => '0')); + + signal a_reg, a_next : std_logic_vector(WIDTHA - 1 downto 0) := (others => '0'); + +begin + + -- read process + process(clkA) + begin + if rising_edge(clkA) then + if rstA = '1' then + a_reg <= (others => '0'); + else + a_reg <= a_next; + end if; + end if; + end process; + --next state logic + a_next <= my_ram(to_integer(unsigned(addrA))) when enA = '1' else a_reg; + doA <= a_reg; + + -- Write process + process(clkB) + begin + if rising_edge(clkB) then + for i in 0 to RATIO - 1 loop + if weB = '1' then + my_ram(to_integer(unsigned(addrB) & to_unsigned(i, log2(RATIO)))) <= diB((i + 1) * minWIDTH - 1 downto i * minWIDTH); + end if; + end loop; + end if; + end process; + +end behavioral; diff --git a/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd b/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd new file mode 100644 index 0000000..9fe4e5a --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd @@ -0,0 +1,253 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_ntoone is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 16; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(O_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(O_DWIDTH-1 downto 0); + + --avg_o : out std_logic_vector(O_DWIDTH-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(2-1 downto 0) + ); +end avg_ntoone; + +architecture rtl of avg_ntoone is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_AVG_N1, + ST_WRITE_AVG, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tdp_dia : std_logic_vector(ADC_DWIDTH-1 downto 0); +signal tdp_doa : std_logic_vector(ADC_DWIDTH-1 downto 0); +signal data_reg, data_next : std_logic_vector(I_DWIDTH-1 downto 0); +signal samples_reg, samples_next : unsigned(ADC_DWIDTH-1 downto 0); + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0); +signal restart_s, restart_os : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0); + +begin + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => MEM_AWIDTH, + DWIDTH => ADC_DWIDTH + ) + port map( + clka => s_axis_aclk, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia, + + clkb => bram_clk, + rstb => bram_rst, + enb => bram_en, + addrb => bram_addr, + dob => bram_rddata + ); + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + tdp_addra_reg <= (others => '0'); + data_reg <= (others => '0'); + samples_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + tdp_addra_reg <= tdp_addra_next; + data_reg <= data_next; + samples_reg <= samples_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, en_i, start_i, trig_i, nsamples_i, + naverages_i, tdp_addra_reg, tdp_dia, data_reg, samples_reg, + s_axis_tvalid, s_axis_tdata, avg_reg, m_axis_tready, restart_os) + variable dinbv : std_logic_vector(ADC_DWIDTH-1 downto 0); + begin + state_next <= state_reg; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + data_next <= data_reg; + samples_next <= samples_reg; + tdp_dia <= (others => '0'); + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + --state_mon <= "0000"; --state mon + samples_next <= (others => '0'); + tdp_addra_next <= (others => '0'); + avg_next <= (others => '0'); + data_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + --state_mon <= "0001"; --state mon + if(trig_i = '1') then + state_next <= ST_AVG_N1; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_AVG_N1 => + --state_mon <= "0010"; + if (s_axis_tvalid = '1') then + tready_s <= '1'; + samples_next <= samples_reg + 1; + ASSIGN_N: for I in 0 to RATIO-1 loop + data_next(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH) <= + std_logic_vector(signed(data_reg(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH)) + + resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH)+4)),ADC_DWIDTH)); + end loop; + if(samples_reg = (unsigned(nsamples_i)/RATIO)-1) then + samples_next <= (others => '0'); + state_next <= ST_WRITE_AVG; + end if; + end if; + + when ST_WRITE_AVG => + --state_mon <= "0011"; + dinbv := (others => '0'); + ASSIGN_AVG1: for K in 0 to RATIO-1 loop + dinbv := std_logic_vector(signed(dinbv) + signed(data_reg(I_DWIDTH-1-K*ADC_DWIDTH downto I_DWIDTH-(K+1)*ADC_DWIDTH))); + end loop; + tdp_dia <= dinbv; + tdp_wea <= '1'; + data_next <= (others => '0'); + tdp_addra_next <= tdp_addra_reg + 1; + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_FINISH => + --state_mon <= "0100"; + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_IDLE; + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_nt: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + reader_i: entity work.bram_reader + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => naverages_i, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/avg_scope.vhd b/cores/axis_avgr16bits_v1_0/avg_scope.vhd new file mode 100644 index 0000000..3ff46ca --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/avg_scope.vhd @@ -0,0 +1,362 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_scope is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 16; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(O_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(O_DWIDTH-1 downto 0); + + --bram_en_o : out std_logic; + --bram_addr_o : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_o : out std_logic_vector(O_DWIDTH-1 downto 0); + --bram_en_oo : out std_logic; + --bram_addr_oo : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_oo : out std_logic_vector(O_DWIDTH-1 downto 0); + --avg_o : out std_logic_vector(O_DWIDTH-1 downto 0); + + --tdp_addra_o : out std_logic_vector(11-1 downto 0); + --tdp_addrb_o : out std_logic_vector(11-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(2-1 downto 0) + ); +end avg_scope; + +architecture rtl of avg_scope is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_EN_TDPB, + ST_AVG_SCOPE, + ST_FINISH, + ST_WR_ZEROS +); +signal state_reg, state_next : state_t; +--signal state_mon_reg, state_mon_next : std_logic_vector(3 downto 0); + +signal rstb_s : std_logic; +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal tdp_dia : std_logic_vector(I_DWIDTH-1 downto 0); +signal tdp_enb : std_logic; +signal tdp_addrb_reg, tdp_addrb_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal tdp_doa, tdp_dob : std_logic_vector(I_DWIDTH-1 downto 0); +signal addrb_s : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); + +signal asy_rsta : std_logic; +signal asy_ena : std_logic; +signal asy_enb : std_logic; +signal asy_web : std_logic; +signal asy_doa : std_logic_vector(ADC_DWIDTH-1 downto 0); + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0); +signal restart_s, restart_os : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0); + +begin + + --state_mon <= state_mon_reg; + --tdp_addra_o <= std_logic_vector(tdp_addra_reg); + --tdp_addrb_o <= std_logic_vector(tdp_addrb_reg); + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => log2c(MEM_DEPTH/RATIO), + DWIDTH => I_DWIDTH + ) + port map( + clka => s_axis_aclk, + --rsta => rsta_s, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia, + + clkb => s_axis_aclk, + rstb => rstb_s, + enb => tdp_enb, --'1', + addrb => std_logic_vector(tdp_addrb_reg), + dob => tdp_dob + ); + + -- ASYMMETRIC RAM + -- Port A -> AXI IF + -- Port B -> same as WIDER BRAM + asy_ram_i : entity work.asym_ram_sdp_write_wider + generic map + ( + WIDTHA => ADC_DWIDTH, + SIZEA => MEM_DEPTH, + ADDRWIDTHA => MEM_AWIDTH, + WIDTHB => I_DWIDTH, + SIZEB => (MEM_DEPTH/RATIO), + ADDRWIDTHB => log2c(MEM_DEPTH/RATIO) + ) + port map + ( + clkA => bram_clk, + rstA => bram_rst, + enA => bram_en, + addrA => bram_addr, + doA => bram_rddata, + + --portB same as portA in tdp_ram + clkB => s_axis_aclk, + weB => tdp_wea, + addrB => std_logic_vector(tdp_addra_reg), + diB => tdp_dia + ); + + --debug signals + --lets synchronize the en signal + --sync_bram_en: entity work.sync + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_en, + -- out_sync => bram_en_o + -- ); + --bram_en_oo <= bram_en; + + --lets synchronize the addr signal + --sync_bram_addr: entity work.n_sync + --generic map( + -- N => MEM_AWIDTH + -- ) + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_addr, + -- out_sync => bram_addr_o + -- ); + --bram_addr_oo <= bram_addr; + + ----lets synchronize the en signal + --sync_bram_rddata: entity work.n_sync + --generic map( + -- N => O_DWIDTH + -- ) + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_rddata, + -- out_sync => bram_rddata_o + -- ); + --bram_rddata_oo <= bram_rddata; + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + --state_mon_reg <= (others => '0'); + tdp_addra_reg <= (others => '0'); + tdp_addrb_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + --state_mon_reg <= state_mon_next; + tdp_addra_reg <= tdp_addra_next; + tdp_addrb_reg <= tdp_addrb_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + --tdp_addra_next <= tdp_addrb_reg; + + --Next state logic + --process(state_reg, state_mon_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, + process(state_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, + tdp_addra_reg, tdp_addrb_reg, tdp_dia, tdp_dob, s_axis_tvalid, s_axis_tdata, + avg_reg, m_axis_tready, restart_os) + begin + state_next <= state_reg; + --state_mon_next<= state_mon_reg; + rstb_s <= '0'; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + tdp_dia <= (others => '0'); + tdp_enb <= '0'; + tdp_addrb_next<= tdp_addrb_reg; + asy_rsta <= '1'; + asy_ena <= '0'; + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + rstb_s <= '1'; + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + else + state_next <= ST_IDLE; + --state_mon_next <= (others => '0'); + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + if(trig_i = '1') then + state_next <= ST_EN_TDPB; + --state_mon_next <= "0010"; + else + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + end if; + + when ST_EN_TDPB => + if (s_axis_tvalid = '1') then + tdp_enb <= '1'; + tdp_addrb_next <= tdp_addrb_reg + 1; + state_next <= ST_AVG_SCOPE; + --state_mon_next <= "0011"; + end if; + + when ST_AVG_SCOPE => -- Measure + if (s_axis_tvalid = '1') then + tready_s <= '1'; + tdp_enb <= '1'; + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + tdp_addrb_next <= tdp_addrb_reg + 1; + ASSIGN_G1: for I in 0 to RATIO-1 loop + tdp_dia(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH) <= + std_logic_vector(signed(tdp_dob(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH)) + + resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH)+4)),ADC_DWIDTH)); + end loop; + if(tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + --state_mon_next <= "0100"; + else + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + end if; + end if; + else + state_next <= ST_AVG_SCOPE; + --state_mon_next <= "0011"; + end if; + + when ST_FINISH => + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_WR_ZEROS; + --state_mon_next <= "0101"; + end if; + + when ST_WR_ZEROS => + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + if (tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + state_next <= ST_IDLE; + --state_mon_next <= (others => '0'); + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_as: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + reader_i: entity work.bram_reader + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => nsamples_i, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/axis_averager.vhd b/cores/axis_avgr16bits_v1_0/axis_averager.vhd new file mode 100644 index 0000000..142e4b2 --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/axis_averager.vhd @@ -0,0 +1,312 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_averager is + generic ( + S_AXIS_DWIDTH : natural := 128; -- AXIS itf data width + M_AXIS_DWIDTH : natural := 16; -- AXI itf data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- MEM addr width + MEM_DEPTH : natural := 1024 --Max 2**16 + ); + port ( + start_i : in std_logic; + trig_i : in std_logic; + send_i : in std_logic; + done_o : out std_logic; + + --start_o : out std_logic; + --trig_o : out std_logic; + --mode_o : out std_logic; + + --avg_scope (as) debug signals + --as_state_mon_o : out std_logic_vector(4-1 downto 0); + --as_avg_o : out std_logic_vector(16-1 downto 0); + + --ntoone (nt) debug signals + --nt_state_mon_o : out std_logic_vector(4-1 downto 0); + --nt_avg_o : out std_logic_vector(16-1 downto 0); + + --en_o : out std_logic; + --nsamples_o : out std_logic_vector(16-1 downto 0); + --naverages_o : out std_logic_vector(16-1 downto 0); + --tdp_addra_o : out std_logic_vector(11-1 downto 0); + --tdp_addrb_o : out std_logic_vector(11-1 downto 0); + --bram_en_o : out std_logic; + --bram_addr_o : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_o : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + --bram_en_oo : out std_logic; + --bram_addr_oo : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_oo : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + + -- Slave config side + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn: in std_logic; + s_axis_cfg_reg_i : in std_logic_vector(80-1 downto 0); + + -- Slave data interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(S_AXIS_DWIDTH-1 downto 0); + + -- Master data interface + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(2-1 downto 0); + m_axis_tdata : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0) + ); +end axis_averager; + +architecture rtl of axis_averager is + + signal en_as, en_nt : std_logic; + signal mode_s, mode_sm : std_logic; + signal done_s, as_done, nt_done : std_logic; + signal start_sync, trig_sync : std_logic; + signal start_os, trig_os, send_os : std_logic; + signal nsamples_s, naverages_s : std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + + --Register cfg/sts + signal s_axis_cfg_reg_sync : std_logic_vector(80-1 downto 0); + signal m_axis_cfg_reg_sync : std_logic_vector(80-1 downto 0); + signal m0_axis_aclk, m1_axis_aclk : std_logic; + signal m0_axis_aresetn, m1_axis_aresetn : std_logic; + signal m0_axis_tdata, m1_axis_tdata : std_logic_vector(S_AXIS_DWIDTH-1 downto 0); + signal m0_axis_tvalid, m1_axis_tvalid : std_logic; + signal m0_axis_tready, m1_axis_tready : std_logic; + + signal m00_axis_aclk, m11_axis_aclk : std_logic; + signal m00_axis_aresetn, m11_axis_aresetn : std_logic; + signal m00_axis_tdata, m11_axis_tdata : std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + signal m00_axis_tvalid, m11_axis_tvalid : std_logic; + signal m00_axis_tready, m11_axis_tready : std_logic; + signal m00_axis_tlast, m11_axis_tlast : std_logic; + signal m00_axis_tkeep, m11_axis_tkeep : std_logic_vector(2-1 downto 0); + +begin + + --lets synchronize the cfg word + sync_cfg_s: entity work.n_sync + generic map(N => 80 + ) + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + in_async => s_axis_cfg_reg_i, + out_sync => s_axis_cfg_reg_sync + ); + + mode_s <= s_axis_cfg_reg_sync(64-1); + naverages_s <= s_axis_cfg_reg_sync(48-1 downto 32); + nsamples_s <= s_axis_cfg_reg_sync(16-1 downto 0); + + --mode_s <= s_axis_cfg_reg_sync(32); + --naverages_s <= s_axis_cfg_reg_sync(32-1 downto 16); + --nsamples_s <= s_axis_cfg_reg_sync(16-1 downto 0); + + --signals for debug + --mode_o <= s_axis_cfg_reg_sync(64-1); + --naverages_o <= s_axis_cfg_reg_sync(48-1 downto 32); + --nsamples_o <= s_axis_cfg_reg_sync(16-1 downto 0); + en_as <= not mode_s; + en_nt <= mode_s; + + --en_o <= en_as; + + os_start: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => start_i, + sig_o => start_os + ); + --start_o <= start_os; + + --lets synchronize the send signal + sync_send_m: entity work.edge_det + port map( + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + sig_i => send_i, + sig_o => send_os + ); + + os_trig: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => trig_i, + sig_o => trig_os + ); + --trig_o <= trig_os; + + --lets synchronize the cfg word + --sync_cfg_m: entity work.n_sync + --generic map(N => 80 + -- ) + --port map( + -- aclk => m_axis_aclk, + -- aresetn => m_axis_aresetn, + -- in_async => s_axis_cfg_reg_i, + -- out_sync => m_axis_cfg_reg_sync + -- ); + ----mode_sm <= m_axis_cfg_reg_sync(32-1); + --mode_sm <= m_axis_cfg_reg_sync(64-1); + + --Select the data input + sig_sel_i: entity work.axis_signal_selector + generic map( + AXIS_DWIDTH => S_AXIS_DWIDTH + ) + port map( + sel => mode_s, + s_axis_aclk => s_axis_aclk, + s_axis_aresetn => s_axis_aresetn, + s_axis_tdata => s_axis_tdata, + s_axis_tvalid => s_axis_tvalid, + s_axis_tready => s_axis_tready, + + m0_axis_aclk => m0_axis_aclk, + m0_axis_aresetn=> m0_axis_aresetn, + m0_axis_tdata => m0_axis_tdata, + m0_axis_tvalid => m0_axis_tvalid, + m0_axis_tready => m0_axis_tready, + + m1_axis_aclk => m1_axis_aclk, + m1_axis_aresetn=> m1_axis_aresetn, + m1_axis_tdata => m1_axis_tdata, + m1_axis_tvalid => m1_axis_tvalid, + m1_axis_tready => m1_axis_tready +); + + --Averager scope + avg_scope_i: entity work.avg_scope + generic map( + I_DWIDTH => S_AXIS_DWIDTH, + O_DWIDTH => M_AXIS_DWIDTH, + ADC_DWIDTH => ADC_DWIDTH, + MEM_AWIDTH => MEM_AWIDTH, + MEM_DEPTH => MEM_DEPTH + ) + port map( + start_i => start_os, + send_i => send_os, + trig_i => trig_os, + done_o => as_done, + --state_mon => as_state_mon_o, + en_i => en_as, + naverages_i => naverages_s, + nsamples_i => nsamples_s, + --bram_en_o => bram_en_o, + --bram_addr_o => bram_addr_o, + --bram_rddata_o => bram_rddata_o, + --bram_en_oo => bram_en_oo, + --bram_addr_oo => bram_addr_oo, + --bram_rddata_oo => bram_rddata_oo, + + --avg_o => as_avg_o, + + --tdp_addra_o => tdp_addra_o, + --tdp_addrb_o => tdp_addrb_o, + + s_axis_cfg_aclk=> s_axis_cfg_aclk, + s_axis_cfg_aresetn => s_axis_cfg_aresetn, + + s_axis_aclk => m0_axis_aclk, + s_axis_aresetn => m0_axis_aresetn, + s_axis_tready => m0_axis_tready, + s_axis_tvalid => m0_axis_tvalid, + s_axis_tdata => m0_axis_tdata, + + m_axis_aclk => m_axis_aclk, + m_axis_aresetn => m_axis_aresetn, + m_axis_tready => m00_axis_tready, + m_axis_tdata => m00_axis_tdata, + m_axis_tvalid => m00_axis_tvalid, + m_axis_tlast => m00_axis_tlast, + m_axis_tkeep => m00_axis_tkeep + ); + + --Averager N to One + avg_ntoone_i: entity work.avg_ntoone + generic map( + I_DWIDTH => S_AXIS_DWIDTH, + O_DWIDTH => M_AXIS_DWIDTH, + ADC_DWIDTH => ADC_DWIDTH, + MEM_AWIDTH => MEM_AWIDTH, + MEM_DEPTH => MEM_DEPTH + ) + port map( + start_i => start_os, + send_i => send_os, + trig_i => trig_os, + done_o => nt_done, + --state_mon => nt_state_mon_o, + en_i => en_nt, + naverages_i => naverages_s, + nsamples_i => nsamples_s, + --avg_o => nt_avg_o, + + s_axis_cfg_aclk=> s_axis_cfg_aclk, + s_axis_cfg_aresetn => s_axis_cfg_aresetn, + + s_axis_aclk => m1_axis_aclk, + s_axis_aresetn => m1_axis_aresetn, + s_axis_tready => m1_axis_tready, + s_axis_tvalid => m1_axis_tvalid, + s_axis_tdata => m1_axis_tdata, + + m_axis_aclk => m_axis_aclk, + m_axis_aresetn => m_axis_aresetn, + m_axis_tready => m11_axis_tready, + m_axis_tdata => m11_axis_tdata, + m_axis_tvalid => m11_axis_tvalid, + m_axis_tlast => m11_axis_tlast, + m_axis_tkeep => m11_axis_tkeep + ); + + done_s <= nt_done when (mode_s = '1') else as_done; + --lets synchronize the done signal + sync_done: entity work.sync + port map( + aclk => s_axis_cfg_aclk, + aresetn => s_axis_cfg_aresetn, + in_async => done_s, + out_sync => done_o + ); + + --Mux the output data + sig_mux_i: entity work.axis_signal_mux + generic map( + AXIS_DWIDTH => M_AXIS_DWIDTH + ) + port map( + sel => mode_s, --m, + + s0_axis_tdata => m00_axis_tdata, + s0_axis_tvalid => m00_axis_tvalid, + s0_axis_tready => m00_axis_tready, + s0_axis_tlast => m00_axis_tlast, + s0_axis_tkeep => m00_axis_tkeep, + + s1_axis_tdata => m11_axis_tdata, + s1_axis_tvalid => m11_axis_tvalid, + s1_axis_tready => m11_axis_tready, + s1_axis_tlast => m11_axis_tlast, + s1_axis_tkeep => m11_axis_tkeep, + + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tready => m_axis_tready, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep + +); + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd b/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd new file mode 100644 index 0000000..5ce0863 --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd @@ -0,0 +1,43 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_signal_mux is +generic ( + AXIS_DWIDTH : natural := 32 +); +port ( + sel : in std_logic; + + s0_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s0_axis_tvalid : in std_logic; + s0_axis_tready : out std_logic; + s0_axis_tlast : in std_logic; + s0_axis_tkeep : in std_logic_vector(2-1 downto 0); + + s1_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s1_axis_tvalid : in std_logic; + s1_axis_tready : out std_logic; + s1_axis_tlast : in std_logic; + s1_axis_tkeep : in std_logic_vector(2-1 downto 0); + + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(2-1 downto 0); + m_axis_tready : in std_logic +); +end axis_signal_mux; + +architecture rtl of axis_signal_mux is +begin + + s0_axis_tready <= m_axis_tready when sel = '0' else '0'; + s1_axis_tready <= m_axis_tready when sel = '1' else '0'; + + m_axis_tdata <= s0_axis_tdata when sel = '0' else s1_axis_tdata; + m_axis_tvalid <= s0_axis_tvalid when sel = '0' else s1_axis_tvalid; + m_axis_tlast <= s0_axis_tlast when sel = '0' else s1_axis_tlast; + m_axis_tkeep <= s0_axis_tkeep when sel = '0' else s1_axis_tkeep; + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd b/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd new file mode 100644 index 0000000..a9bda66 --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_signal_selector is +generic ( + AXIS_DWIDTH : natural := 32 +); +port ( + sel : in std_logic; + -- System signals + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + s_axis_tready : out std_logic; + + m0_axis_aclk : out std_logic; + m0_axis_aresetn : out std_logic; + m0_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m0_axis_tvalid : out std_logic; + m0_axis_tready : in std_logic; + + m1_axis_aclk : out std_logic; + m1_axis_aresetn : out std_logic; + m1_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m1_axis_tvalid : out std_logic; + m1_axis_tready : in std_logic +); +end axis_signal_selector; + +architecture rtl of axis_signal_selector is +begin + m0_axis_aclk <= s_axis_aclk; + m0_axis_aresetn <= s_axis_aresetn; + + m1_axis_aclk <= s_axis_aclk; + m1_axis_aresetn <= s_axis_aresetn; + + s_axis_tready <= m0_axis_tready when sel = '0' else m1_axis_tready; + + m0_axis_tvalid <= s_axis_tvalid when sel = '0' else '0'; + m0_axis_tdata <= s_axis_tdata when sel = '0' else (others => '0'); + + m1_axis_tvalid <= s_axis_tvalid when sel = '1' else '0'; + m1_axis_tdata <= s_axis_tdata when sel = '1' else (others => '0'); + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/bram_reader.vhd b/cores/axis_avgr16bits_v1_0/bram_reader.vhd new file mode 100644 index 0000000..78184ad --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/bram_reader.vhd @@ -0,0 +1,150 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bram_reader is + generic ( + MEM_DEPTH : natural := 1024; + MEM_AWIDTH : natural := 10; + AXIS_DWIDTH : natural := 16 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data_i : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + --sts_data_o : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + done_i : in std_logic; + send_i : in std_logic; + restart_o : out std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(2-1 downto 0); + + -- BRAM port + bram_clk : out std_logic; + bram_rst : out std_logic; + bram_en : out std_logic; + bram_addr : out std_logic_vector(MEM_AWIDTH-1 downto 0); + bram_rddata : in std_logic_vector(AXIS_DWIDTH-1 downto 0) + ); +end bram_reader; + +architecture rtl of bram_reader is + + type state_t is ( + ST_IDLE, + ST_EN_BRAM, + ST_SEND_DATA, + ST_TLAST, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tlast_s, rst_s, en_s : std_logic; +signal tvalid_s : std_logic; +signal restart_s : std_logic; +signal tkeep_s : std_logic_vector(2-1 downto 0); +--signal bram_st_mon : std_logic_vector(4-1 downto 0); + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + state_reg <= ST_IDLE; + addr_reg <= (others => '0'); + else + state_reg <= state_next; + addr_reg <= addr_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, addr_reg, done_i, send_i, m_axis_tready, + cfg_data_i) + begin + state_next <= state_reg; + addr_next <= addr_reg; + tvalid_s <= '0'; + tlast_s <= '0'; + restart_s <= '0'; + en_s <= '0'; + rst_s <= '0'; + tkeep_s <= (others => '0'); + + case state_reg is + when ST_IDLE => + --bram_st_mon <= "0000"; --state mon + rst_s <= '1'; + addr_next <= (others => '0'); + if (done_i = '1') and (send_i = '1') then + state_next <= ST_EN_BRAM; + else + state_next <= ST_IDLE; + end if; + + when ST_EN_BRAM => + --bram_st_mon <= "0001"; --state mon + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + state_next <= ST_SEND_DATA; + else + state_next <= ST_EN_BRAM; + end if; + + when ST_SEND_DATA => + --bram_st_mon <= "0010"; --state mon + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + if (addr_reg = unsigned(cfg_data_i)-1) then + --addr_next <= (others => '0'); + state_next <= ST_TLAST; + else + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + + when ST_TLAST => + --bram_st_mon <= "0011"; + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + tlast_s <= '1'; + state_next <= ST_FINISH; + + when ST_FINISH => + --bram_st_mon <= "0100"; --state mon + restart_s <= '1'; + state_next <= ST_IDLE; + + end case; + end process; + + --sts_data_o <= std_logic_vector(resize(addr_reg,AXIS_DWIDTH)); + + m_axis_tdata <= bram_rddata; + m_axis_tvalid <= tvalid_s; + m_axis_tlast <= tlast_s; + m_axis_tkeep <= tkeep_s; + + bram_clk <= aclk; + bram_rst <= rst_s; + bram_en <= en_s; + bram_addr <= std_logic_vector(addr_reg); + restart_o <= restart_s; + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/core_config.tcl b/cores/axis_avgr16bits_v1_0/core_config.tcl new file mode 100644 index 0000000..500daba --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/core_config.tcl @@ -0,0 +1,29 @@ +set display_name {AXI4-Stream Averager 16 bits v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter S_AXIS_DWIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter M_AXIS_DWIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.} +core_parameter ADC_DWIDTH {ADC DATA WIDTH} {Width of the ADC data.} +core_parameter MEM_AWIDTH {MEMORY ADDR WIDTH} {Address width of the data memory.} +core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces m_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter + diff --git a/cores/axis_avgr16bits_v1_0/edge_det.vhd b/cores/axis_avgr16bits_v1_0/edge_det.vhd new file mode 100644 index 0000000..11dfb19 --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/edge_det.vhd @@ -0,0 +1,58 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity edge_det is + port( + aclk : in std_logic; + aresetn: in std_logic; + sig_i : in std_logic; + sig_o : out std_logic + ); +end edge_det; + +architecture rtl of edge_det is + type state_t is (zero, edge, one); + signal state_reg, state_next: state_t; +begin + -- state register + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + state_reg <= zero; + else + state_reg <= state_next; + end if; + end if; + end process; + + -- next-state logic + process(state_reg, sig_i) + begin + case state_reg is + when zero=> + if sig_i = '1' then + state_next <= edge; + else + state_next <= zero; + end if; + when edge => + if sig_i = '1' then + state_next <= one; + else + state_next <= zero; + end if; + when one => + if sig_i = '1' then + state_next <= one; + else + state_next <= zero; + end if; + end case; + end process; + + -- Moore output logic + sig_o <= '1' when state_reg=edge else + '0'; + +end rtl; diff --git a/cores/axis_avgr16bits_v1_0/n_sync.vhd b/cores/axis_avgr16bits_v1_0/n_sync.vhd new file mode 100644 index 0000000..1a92e1d --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/n_sync.vhd @@ -0,0 +1,46 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity n_sync is + generic( + N : natural + ); + port( + aclk : in std_logic; + aresetn : in std_logic; + in_async : in std_logic_vector(N-1 downto 0); + out_sync : out std_logic_vector(N-1 downto 0) + ); +end n_sync; + +architecture two_ff_arch of n_sync is + signal meta_reg, meta_next : std_logic_vector(N-1 downto 0); + signal sync_reg, sync_next: std_logic_vector(N-1 downto 0); + + attribute ASYNC_REG : string; + attribute ASYNC_REG of meta_reg: signal is "TRUE"; + attribute ASYNC_REG of sync_reg: signal is "TRUE"; + +begin + + -- two registers + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + meta_reg <= (others=>'0'); + sync_reg <= (others=>'0'); + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr16bits_v1_0/sync.vhd b/cores/axis_avgr16bits_v1_0/sync.vhd new file mode 100644 index 0000000..492bcf6 --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/sync.vhd @@ -0,0 +1,43 @@ +library ieee; +use ieee.std_logic_1164.all; + +--synchronizer +entity sync is + port( + aclk : in std_logic; + aresetn : in std_logic; + in_async : in std_logic; + out_sync : out std_logic + ); +end sync; + +architecture two_ff_arch of sync is + signal meta_reg, meta_next : std_logic; + signal sync_reg, sync_next: std_logic; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of meta_reg: signal is "TRUE"; + attribute ASYNC_REG of sync_reg: signal is "TRUE"; +begin + + -- two registers + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + meta_reg <= '0'; + sync_reg <= '0'; + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd b/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd new file mode 100644 index 0000000..712f43a --- /dev/null +++ b/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd @@ -0,0 +1,86 @@ +-- Block RAM with Optional Output Registers +-- File: modified from rams_pipeline.vhd +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity tdp_ram_pip is + generic ( + AWIDTH : integer := 16; + DWIDTH : integer := 16 + ); + port( + clka : in std_logic; + --rsta : in std_logic; + --ena : in std_logic; + wea : in std_logic; + addra : in std_logic_vector(AWIDTH-1 downto 0); + dia : in std_logic_vector(DWIDTH-1 downto 0); + --doa : out std_logic_vector(DWIDTH-1 downto 0); + clkb : in std_logic; + rstb : in std_logic; + enb : in std_logic; + --web : in std_logic; + addrb : in std_logic_vector(AWIDTH-1 downto 0); + --dib : in std_logic_vector(DWIDTH-1 downto 0); + dob : out std_logic_vector(DWIDTH-1 downto 0) + ); +end tdp_ram_pip; + +architecture rtl of tdp_ram_pip is + type ram_t is array (0 to 2**AWIDTH-1) of std_logic_vector(DWIDTH-1 downto 0); + signal ram : ram_t := (others => (others => '0')); + signal a_reg, a_next : std_logic_vector(DWIDTH-1 downto 0); + signal b_reg, b_next : std_logic_vector(DWIDTH-1 downto 0); + +begin + + process(clka) + begin + if rising_edge(clka) then + if wea = '1' then + ram(to_integer(unsigned(addra))) <= dia; + end if; + --do1 <= ram(to_integer(unsigned(addra))); + end if; + end process; + + --process(clka) + --begin + -- if rising_edge(clka) then + -- if rsta = '1' then + -- a_reg <= (others => '0'); + -- else + -- a_reg <= a_next; + -- end if; + -- end if; + --end process; + ----next state logic + --a_next <= ram(to_integer(unsigned(addra))) when ena = '1' else a_reg; + --doa <= a_reg; + + --process(clkb) + --begin + -- if rising_edge(clkb) then + -- if web = '1' then + -- ram(to_integer(unsigned(addrb))) <= dib; + -- end if; + -- --do2 <= ram(to_integer(unsigned(addrb))); + -- end if; + --end process; + + process(clkb) + begin + if rising_edge(clkb) then + if rstb = '1' then + b_reg <= (others => '0'); + else + b_reg <= b_next; + end if; + end if; + end process; + --next state logic + b_next <= ram(to_integer(unsigned(addrb))) when enb = '1' else b_reg; + dob <= b_reg; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd b/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd new file mode 100644 index 0000000..7546098 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd @@ -0,0 +1,255 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_ntoone is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 32; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + + --avg_o : out std_logic_vector(O_DWIDTH-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0) + ); +end avg_ntoone; + +architecture rtl of avg_ntoone is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_AVG_N1, + ST_WRITE_AVG, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tdp_dia : std_logic_vector(O_DWIDTH-1 downto 0); +signal tdp_doa : std_logic_vector(O_DWIDTH-1 downto 0); +signal data_reg, data_next : std_logic_vector(2*I_DWIDTH-1 downto 0); +signal samples_reg, samples_next : unsigned(ADC_DWIDTH-1 downto 0); + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next : unsigned(ADC_DWIDTH-1 downto 0); +signal restart_s, restart_os : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0); +signal naverages_b : std_logic_vector(O_DWIDTH-1 downto 0); + +begin + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => MEM_AWIDTH, + DWIDTH => O_DWIDTH + ) + port map( + clka => s_axis_aclk, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia, + + clkb => bram_clk, + rstb => bram_rst, + enb => bram_en, + addrb => bram_addr, + dob => bram_rddata + ); + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + tdp_addra_reg <= (others => '0'); + data_reg <= (others => '0'); + samples_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + tdp_addra_reg <= tdp_addra_next; + data_reg <= data_next; + samples_reg <= samples_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, en_i, start_i, trig_i, nsamples_i, + naverages_i, tdp_addra_reg, tdp_dia, data_reg, samples_reg, + s_axis_tvalid, s_axis_tdata, avg_reg, m_axis_tready, restart_os) + variable dinbv : std_logic_vector(O_DWIDTH-1 downto 0); + begin + state_next <= state_reg; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + data_next <= data_reg; + samples_next <= samples_reg; + tdp_dia <= (others => '0'); + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + --state_mon <= "0000"; --state mon + samples_next <= (others => '0'); + tdp_addra_next <= (others => '0'); + avg_next <= (others => '0'); + data_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + --state_mon <= "0001"; --state mon + if(trig_i = '1') then + state_next <= ST_AVG_N1; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_AVG_N1 => + --state_mon <= "0010"; + if (s_axis_tvalid = '1') then + tready_s <= '1'; + samples_next <= samples_reg + 1; + ASSIGN_N: for I in 0 to RATIO-1 loop + data_next(2*I_DWIDTH-1-I*O_DWIDTH downto 2*I_DWIDTH-(I+1)*O_DWIDTH) <= + std_logic_vector(signed(data_reg(2*I_DWIDTH-1-I*O_DWIDTH downto 2*I_DWIDTH-(I+1)*O_DWIDTH)) + + resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH))),O_DWIDTH)); + end loop; + if(samples_reg = (unsigned(nsamples_i)/RATIO)-1) then + samples_next <= (others => '0'); + state_next <= ST_WRITE_AVG; + end if; + end if; + + when ST_WRITE_AVG => + --state_mon <= "0011"; + dinbv := (others => '0'); + ASSIGN_AVG1: for K in 0 to RATIO-1 loop + dinbv := std_logic_vector(signed(dinbv) + signed(data_reg(2*I_DWIDTH-1-K*O_DWIDTH downto 2*I_DWIDTH-(K+1)*O_DWIDTH))); + end loop; + tdp_dia <= dinbv; + tdp_wea <= '1'; + data_next <= (others => '0'); + tdp_addra_next <= tdp_addra_reg + 1; + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_FINISH => + --state_mon <= "0100"; + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_IDLE; + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_nt: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + naverages_b <= (31 downto 16 => '0') & naverages_i; + reader_i: entity work.bram_reader_nt + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => naverages_s, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/avg_scope.vhd b/cores/axis_avgr32bits_v1_0/avg_scope.vhd new file mode 100644 index 0000000..ec3809a --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/avg_scope.vhd @@ -0,0 +1,318 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_scope is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 32; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + --avg_o : out std_logic_vector(16-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0) + ); +end avg_scope; + +architecture rtl of avg_scope is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_EN_TDPB, + ST_AVG_SCOPE, + ST_FINISH, + ST_WR_ZEROS +); +signal state_reg, state_next : state_t; + +signal rstb_s : std_logic; +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tdp_enb : std_logic; +signal tdp_addrb_reg, tdp_addrb_next : unsigned(MEM_AWIDTH-1 downto 0); +signal addrb_s : std_logic_vector(MEM_AWIDTH-1 downto 0); + + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next : unsigned(ADC_DWIDTH-1 downto 0); +signal en_s, restart_s : std_logic; +signal start_sync, trig_sync, send_sync, restart_sync : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(2*I_DWIDTH-1 downto 0); + +type vect_t is array (0 to RATIO-1) of std_logic_vector(O_DWIDTH-1 downto 0); +signal in_reg, in_next : vect_t; +signal tdp_dia, tdp_doa, tdp_dob, bram_rddata_s : vect_t; +signal tvalid_reg, tvalid_next : std_logic; +signal reader_cfg : std_logic_vector(16-1 downto 0); + +begin + + --en_s <= not cfg_data_i(32); --mode=0 enables this block + --naverages_s <= cfg_data_i(32-1 downto 16); + --nsamples_s <= cfg_data_i(16-1 downto 0); + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + -- input assignment + process(s_axis_tvalid, s_axis_tdata) + begin + if (s_axis_tvalid = '1') then + for k in 0 to RATIO-1 loop + in_next(k) <= std_logic_vector(resize(signed(s_axis_tdata(I_DWIDTH-1-k*ADC_DWIDTH downto I_DWIDTH-(k+1)*ADC_DWIDTH)),O_DWIDTH)); + end loop; + else + for k in 0 to RATIO-1 loop + in_next(k) <= in_reg(k); + end loop; + end if; + end process; + + BRAM_CALC_inst: for j in 0 to RATIO-1 generate + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => MEM_AWIDTH, + DWIDTH => O_DWIDTH + ) + port map( + clka => s_axis_aclk, + --rsta => rsta_s, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia(j), + + clkb => s_axis_aclk, + rstb => rstb_s, + enb => tdp_enb, --'1', + addrb => std_logic_vector(tdp_addrb_reg), + dob => tdp_dob(j) + ); +end generate; + + BRAM_OUT_inst: for j in 0 to RATIO-1 generate + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => MEM_AWIDTH, + DWIDTH => O_DWIDTH + ) + port map( + clka => s_axis_aclk, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia(j), + + clkb => bram_clk, + rstb => bram_rst, + enb => bram_en, + addrb => bram_addr, + dob => bram_rddata_s(j) + ); +end generate; + +process(bram_rddata_s) +begin + for k in 0 to RATIO-1 loop + bram_rddata(2*I_DWIDTH-1-k*O_DWIDTH downto 2*I_DWIDTH-(k+1)*O_DWIDTH) <= bram_rddata_s(RATIO-1-k); + end loop; +end process; + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + in_reg <= (others => (others => '0')); + tvalid_reg <= '0'; + tdp_addra_reg <= (others => '0'); + tdp_addrb_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + in_reg <= in_next; + tvalid_reg <= tvalid_next; + tdp_addra_reg <= tdp_addra_next; + tdp_addrb_reg <= tdp_addrb_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + tvalid_next <= s_axis_tvalid; -- one clk delay + + --Next state logic + process(state_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, + tdp_addra_reg, tdp_addrb_reg, tdp_dia, tvalid_reg, + avg_reg, m_axis_tready, restart_os) + begin + state_next <= state_reg; + rstb_s <= '0'; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + tdp_dia <= (others => (others => '0')); + tdp_enb <= '0'; + tdp_addrb_next<= tdp_addrb_reg; + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + rstb_s <= '1'; + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + if(trig_i = '1') then + state_next <= ST_EN_TDPB; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_EN_TDPB => + if (tvalid_reg = '1') then + tdp_enb <= '1'; + tdp_addrb_next <= tdp_addrb_reg + 1; + state_next <= ST_AVG_SCOPE; + end if; + + when ST_AVG_SCOPE => -- Measure + if (tvalid_reg = '1') then + tready_s <= '1'; + tdp_enb <= '1'; + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + tdp_addrb_next <= tdp_addrb_reg + 1; + ASSIGN_G1: for I in 0 to RATIO-1 loop + tdp_dia(I) <= std_logic_vector(signed(tdp_dob(I)) + signed(in_reg(I))); + end loop; + if(tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + end if; + else + state_next <= ST_AVG_SCOPE; + end if; + + when ST_FINISH => + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_WR_ZEROS; + end if; + + when ST_WR_ZEROS => + state_mon <= "0101"; + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + if (tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + state_next <= ST_IDLE; + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_as: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + reader_cfg <= std_logic_vector(unsigned(nsamples_i)/RATIO); + reader_i: entity work.bram_reader + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + DRATIO => RATIO, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => reader_cfg, --nsamples_s, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/axis_averager.vhd b/cores/axis_avgr32bits_v1_0/axis_averager.vhd new file mode 100644 index 0000000..f0f1bc9 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/axis_averager.vhd @@ -0,0 +1,311 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_averager is + generic ( + S_AXIS_DWIDTH : natural := 128; -- AXIS itf data width + M_AXIS_DWIDTH : natural := 32; -- AXI itf data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- MEM addr width + MEM_DEPTH : natural := 1024 --Max 2**16 + ); + port ( + start_i : in std_logic; + trig_i : in std_logic; + send_i : in std_logic; + done_o : out std_logic; + + --start_o : out std_logic; + --trig_o : out std_logic; + --mode_o : out std_logic; + + --avg_scope (as) debug signals + --as_state_mon_o : out std_logic_vector(4-1 downto 0); + --as_avg_o : out std_logic_vector(16-1 downto 0); + + --ntoone (nt) debug signals + --nt_state_mon_o : out std_logic_vector(4-1 downto 0); + --nt_avg_o : out std_logic_vector(16-1 downto 0); + + --en_o : out std_logic; + --nsamples_o : out std_logic_vector(16-1 downto 0); + --naverages_o : out std_logic_vector(16-1 downto 0); + --tdp_addra_o : out std_logic_vector(11-1 downto 0); + --tdp_addrb_o : out std_logic_vector(11-1 downto 0); + --bram_en_o : out std_logic; + --bram_addr_o : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_o : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + --bram_en_oo : out std_logic; + --bram_addr_oo : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_oo : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + + -- Slave config side + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn: in std_logic; + s_axis_cfg_reg_i : in std_logic_vector(80-1 downto 0); + + -- Slave data interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(S_AXIS_DWIDTH-1 downto 0); + + -- Master data interface + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0); + m_axis_tdata : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0) + ); +end axis_averager; + +architecture rtl of axis_averager is + + signal en_as, en_nt : std_logic; + signal mode_s, mode_sm : std_logic; + signal done_s, as_done, nt_done : std_logic; + signal start_sync, trig_sync : std_logic; + signal start_os, trig_os, send_os : std_logic; + signal nsamples_s, naverages_s : std_logic_vector(ADC_DWIDTH-1 downto 0); + + --Register cfg/sts + signal s_axis_cfg_reg_sync : std_logic_vector(80-1 downto 0); + signal m_axis_cfg_reg_sync : std_logic_vector(80-1 downto 0); + signal m0_axis_aclk, m1_axis_aclk : std_logic; + signal m0_axis_aresetn, m1_axis_aresetn : std_logic; + signal m0_axis_tdata, m1_axis_tdata : std_logic_vector(S_AXIS_DWIDTH-1 downto 0); + signal m0_axis_tvalid, m1_axis_tvalid : std_logic; + signal m0_axis_tready, m1_axis_tready : std_logic; + + signal m00_axis_aclk, m11_axis_aclk : std_logic; + signal m00_axis_aresetn, m11_axis_aresetn : std_logic; + signal m00_axis_tdata, m11_axis_tdata : std_logic_vector(M_AXIS_DWIDTH-1 downto 0); + signal m00_axis_tvalid, m11_axis_tvalid : std_logic; + signal m00_axis_tready, m11_axis_tready : std_logic; + signal m00_axis_tlast, m11_axis_tlast : std_logic; + signal m00_axis_tkeep, m11_axis_tkeep : std_logic_vector(4-1 downto 0); + +begin + + --lets synchronize the cfg word + sync_cfg_s: entity work.n_sync + generic map(N => 80 + ) + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + in_async => s_axis_cfg_reg_i, + out_sync => s_axis_cfg_reg_sync + ); + + --mode_s <= s_axis_cfg_reg_sync(64-1); + --naverages_s <= s_axis_cfg_reg_sync(48-1 downto 32); + --nsamples_s <= s_axis_cfg_reg_sync(16-1 downto 0); + mode_s <= s_axis_cfg_reg_sync(32); + naverages_s <= s_axis_cfg_reg_sync(32-1 downto 16); + nsamples_s <= s_axis_cfg_reg_sync(16-1 downto 0); + + --signals for debug + --mode_o <= s_axis_cfg_reg_sync(64-1); + --naverages_o <= s_axis_cfg_reg_sync(48-1 downto 32); + --nsamples_o <= s_axis_cfg_reg_sync(16-1 downto 0); + en_as <= not mode_s; + en_nt <= mode_s; + + --en_o <= en_as; + + os_start: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => start_i, + sig_o => start_os + ); + --start_o <= start_os; + + --lets synchronize the send signal + sync_send_m: entity work.edge_det + port map( + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + sig_i => send_i, + sig_o => send_os + ); + + os_trig: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => trig_i, + sig_o => trig_os + ); + --trig_o <= trig_os; + + --lets synchronize the cfg word + --sync_cfg_m: entity work.n_sync + --generic map(N => 80 + -- ) + --port map( + -- aclk => m_axis_aclk, + -- aresetn => m_axis_aresetn, + -- in_async => s_axis_cfg_reg_i, + -- out_sync => m_axis_cfg_reg_sync + -- ); + ----mode_sm <= m_axis_cfg_reg_sync(32-1); + --mode_sm <= m_axis_cfg_reg_sync(64-1); + + --Select the data input + sig_sel_i: entity work.axis_signal_selector + generic map( + AXIS_DWIDTH => S_AXIS_DWIDTH + ) + port map( + sel => mode_s, + s_axis_aclk => s_axis_aclk, + s_axis_aresetn => s_axis_aresetn, + s_axis_tdata => s_axis_tdata, + s_axis_tvalid => s_axis_tvalid, + s_axis_tready => s_axis_tready, + + m0_axis_aclk => m0_axis_aclk, + m0_axis_aresetn=> m0_axis_aresetn, + m0_axis_tdata => m0_axis_tdata, + m0_axis_tvalid => m0_axis_tvalid, + m0_axis_tready => m0_axis_tready, + + m1_axis_aclk => m1_axis_aclk, + m1_axis_aresetn=> m1_axis_aresetn, + m1_axis_tdata => m1_axis_tdata, + m1_axis_tvalid => m1_axis_tvalid, + m1_axis_tready => m1_axis_tready +); + + --Averager scope + avg_scope_i: entity work.avg_scope + generic map( + I_DWIDTH => S_AXIS_DWIDTH, + O_DWIDTH => M_AXIS_DWIDTH, + ADC_DWIDTH => ADC_DWIDTH, + MEM_AWIDTH => MEM_AWIDTH, + MEM_DEPTH => MEM_DEPTH + ) + port map( + start_i => start_os, + send_i => send_os, + trig_i => trig_os, + done_o => as_done, + --state_mon => as_state_mon_o, + en_i => en_as, + naverages_i => naverages_s, + nsamples_i => nsamples_s, + --bram_en_o => bram_en_o, + --bram_addr_o => bram_addr_o, + --bram_rddata_o => bram_rddata_o, + --bram_en_oo => bram_en_oo, + --bram_addr_oo => bram_addr_oo, + --bram_rddata_oo => bram_rddata_oo, + + --avg_o => as_avg_o, + + --tdp_addra_o => tdp_addra_o, + --tdp_addrb_o => tdp_addrb_o, + + s_axis_cfg_aclk=> s_axis_cfg_aclk, + s_axis_cfg_aresetn => s_axis_cfg_aresetn, + + s_axis_aclk => m0_axis_aclk, + s_axis_aresetn => m0_axis_aresetn, + s_axis_tready => m0_axis_tready, + s_axis_tvalid => m0_axis_tvalid, + s_axis_tdata => m0_axis_tdata, + + m_axis_aclk => m_axis_aclk, + m_axis_aresetn => m_axis_aresetn, + m_axis_tready => m00_axis_tready, + m_axis_tdata => m00_axis_tdata, + m_axis_tvalid => m00_axis_tvalid, + m_axis_tlast => m00_axis_tlast, + m_axis_tkeep => m00_axis_tkeep + ); + + --Averager N to One + avg_ntoone_i: entity work.avg_ntoone + generic map( + I_DWIDTH => S_AXIS_DWIDTH, + O_DWIDTH => M_AXIS_DWIDTH, + ADC_DWIDTH => ADC_DWIDTH, + MEM_AWIDTH => MEM_AWIDTH, + MEM_DEPTH => MEM_DEPTH + ) + port map( + start_i => start_os, + send_i => send_os, + trig_i => trig_os, + done_o => nt_done, + --state_mon => nt_state_mon_o, + en_i => en_nt, + naverages_i => naverages_s, + nsamples_i => nsamples_s, + --avg_o => nt_avg_o, + + s_axis_cfg_aclk=> s_axis_cfg_aclk, + s_axis_cfg_aresetn => s_axis_cfg_aresetn, + + s_axis_aclk => m1_axis_aclk, + s_axis_aresetn => m1_axis_aresetn, + s_axis_tready => m1_axis_tready, + s_axis_tvalid => m1_axis_tvalid, + s_axis_tdata => m1_axis_tdata, + + m_axis_aclk => m_axis_aclk, + m_axis_aresetn => m_axis_aresetn, + m_axis_tready => m11_axis_tready, + m_axis_tdata => m11_axis_tdata, + m_axis_tvalid => m11_axis_tvalid, + m_axis_tlast => m11_axis_tlast, + m_axis_tkeep => m11_axis_tkeep + ); + + done_s <= nt_done when (mode_s = '1') else as_done; + --lets synchronize the done signal + sync_done: entity work.sync + port map( + aclk => s_axis_cfg_aclk, + aresetn => s_axis_cfg_aresetn, + in_async => done_s, + out_sync => done_o + ); + + --Mux the output data + sig_mux_i: entity work.axis_signal_mux + generic map( + AXIS_DWIDTH => M_AXIS_DWIDTH + ) + port map( + sel => mode_s, --m, + + s0_axis_tdata => m00_axis_tdata, + s0_axis_tvalid => m00_axis_tvalid, + s0_axis_tready => m00_axis_tready, + s0_axis_tlast => m00_axis_tlast, + s0_axis_tkeep => m00_axis_tkeep, + + s1_axis_tdata => m11_axis_tdata, + s1_axis_tvalid => m11_axis_tvalid, + s1_axis_tready => m11_axis_tready, + s1_axis_tlast => m11_axis_tlast, + s1_axis_tkeep => m11_axis_tkeep, + + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tready => m_axis_tready, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep + +); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd b/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd new file mode 100644 index 0000000..79f91ec --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd @@ -0,0 +1,43 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_signal_mux is +generic ( + AXIS_DWIDTH : natural := 32 +); +port ( + sel : in std_logic; + + s0_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s0_axis_tvalid : in std_logic; + s0_axis_tready : out std_logic; + s0_axis_tlast : in std_logic; + s0_axis_tkeep : in std_logic_vector(4-1 downto 0); + + s1_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s1_axis_tvalid : in std_logic; + s1_axis_tready : out std_logic; + s1_axis_tlast : in std_logic; + s1_axis_tkeep : in std_logic_vector(4-1 downto 0); + + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0); + m_axis_tready : in std_logic +); +end axis_signal_mux; + +architecture rtl of axis_signal_mux is +begin + + s0_axis_tready <= m_axis_tready when sel = '0' else '0'; + s1_axis_tready <= m_axis_tready when sel = '1' else '0'; + + m_axis_tdata <= s0_axis_tdata when sel = '0' else s1_axis_tdata; + m_axis_tvalid <= s0_axis_tvalid when sel = '0' else s1_axis_tvalid; + m_axis_tlast <= s0_axis_tlast when sel = '0' else s1_axis_tlast; + m_axis_tkeep <= s0_axis_tkeep when sel = '0' else s1_axis_tkeep; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd b/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd new file mode 100644 index 0000000..a9bda66 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_signal_selector is +generic ( + AXIS_DWIDTH : natural := 32 +); +port ( + sel : in std_logic; + -- System signals + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + s_axis_tready : out std_logic; + + m0_axis_aclk : out std_logic; + m0_axis_aresetn : out std_logic; + m0_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m0_axis_tvalid : out std_logic; + m0_axis_tready : in std_logic; + + m1_axis_aclk : out std_logic; + m1_axis_aresetn : out std_logic; + m1_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m1_axis_tvalid : out std_logic; + m1_axis_tready : in std_logic +); +end axis_signal_selector; + +architecture rtl of axis_signal_selector is +begin + m0_axis_aclk <= s_axis_aclk; + m0_axis_aresetn <= s_axis_aresetn; + + m1_axis_aclk <= s_axis_aclk; + m1_axis_aresetn <= s_axis_aresetn; + + s_axis_tready <= m0_axis_tready when sel = '0' else m1_axis_tready; + + m0_axis_tvalid <= s_axis_tvalid when sel = '0' else '0'; + m0_axis_tdata <= s_axis_tdata when sel = '0' else (others => '0'); + + m1_axis_tvalid <= s_axis_tvalid when sel = '1' else '0'; + m1_axis_tdata <= s_axis_tdata when sel = '1' else (others => '0'); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/bram_reader.vhd b/cores/axis_avgr32bits_v1_0/bram_reader.vhd new file mode 100644 index 0000000..9bd369d --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/bram_reader.vhd @@ -0,0 +1,184 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bram_reader is + generic ( + MEM_DEPTH : natural := 1024; + MEM_AWIDTH : natural := 10; + DRATIO : natural := 8; + AXIS_DWIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data_i : in std_logic_vector(16-1 downto 0); + --sts_data_o : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + done_i : in std_logic; + send_i : in std_logic; + restart_o : out std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0); + + -- BRAM port + bram_clk : out std_logic; + bram_rst : out std_logic; + bram_en : out std_logic; + bram_addr : out std_logic_vector(MEM_AWIDTH-1 downto 0); + bram_rddata : in std_logic_vector((DRATIO*AXIS_DWIDTH)-1 downto 0) + ); +end bram_reader; + +architecture rtl of bram_reader is + + type state_t is ( + ST_IDLE, + ST_EN_BRAM, + ST_LOAD_DATA, + ST_SEND_DATA, + --ST_TLAST, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tlast_s, rst_s, en_s : std_logic; +signal tvalid_s : std_logic; +signal restart_s : std_logic; +signal tkeep_s : std_logic_vector(4-1 downto 0); +--signal bram_st_mon : std_logic_vector(4-1 downto 0); +signal load_s : std_logic; +signal cntr_reg, cntr_next : unsigned(DRATIO-1 downto 0); --4 should be enough + +begin + + sh_reg_i : entity work.shift_reg_vect + generic map( + DWIDTH => 32, + DRATIO => 8 + ) + port map( + aclk => aclk, + --serin => (others => '0'), + load => load_s, + parin => bram_rddata, + serout => m_axis_tdata + ); + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + state_reg <= ST_IDLE; + addr_reg <= (others => '0'); + cntr_reg <= (others => '0'); + else + state_reg <= state_next; + addr_reg <= addr_next; + cntr_reg <= cntr_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, addr_reg, cntr_reg, done_i, send_i, m_axis_tready, + cfg_data_i) + begin + state_next <= state_reg; + addr_next <= addr_reg; + cntr_next <= cntr_reg; + tvalid_s <= '0'; + tlast_s <= '0'; + restart_s <= '0'; + en_s <= '0'; + rst_s <= '0'; + load_s <= '0'; + tkeep_s <= (others => '0'); + + case state_reg is + when ST_IDLE => + --bram_st_mon <= "0000"; --state mon + rst_s <= '1'; + addr_next <= (others => '0'); + if (done_i = '1') and (send_i = '1') then + state_next <= ST_EN_BRAM; + else + state_next <= ST_IDLE; + end if; + + when ST_EN_BRAM => + --bram_st_mon <= "0001"; --state mon + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + state_next <= ST_LOAD_DATA; + else + state_next <= ST_EN_BRAM; + end if; + + when ST_LOAD_DATA => + en_s <= '1'; + load_s <= '1'; + state_next <= ST_SEND_DATA; + + when ST_SEND_DATA => + --bram_st_mon <= "0010"; --state mon + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + if m_axis_tready = '1' then + cntr_next <= cntr_reg + 1; + if (cntr_reg = DRATIO-1) then + addr_next <= addr_reg + 1; + if (addr_reg = unsigned(cfg_data_i)) then + addr_next <= (others => '0'); + tlast_s <= '1'; + cntr_next <= (others => '0'); + state_next <= ST_FINISH; + else + en_s <= '1'; + load_s <= '1'; + cntr_next <= (others => '0'); + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + + --when ST_TLAST => + -- bram_st_mon <= "0011"; + -- tvalid_s <= '1'; + -- tlast_s <= '1'; + -- state_next <= ST_FINISH; + + when ST_FINISH => + --bram_st_mon <= "0011"; --state mon + restart_s <= '1'; + state_next <= ST_IDLE; + + end case; + end process; + + --sts_data_o <= std_logic_vector(resize(addr_reg,AXIS_DWIDTH)); + +--m_axis_tdata <= bram_rddata; + m_axis_tvalid <= tvalid_s; + m_axis_tlast <= tlast_s; + m_axis_tkeep <= tkeep_s; + + bram_clk <= aclk; + bram_rst <= rst_s; + bram_en <= en_s; + bram_addr <= std_logic_vector(addr_reg); + restart_o <= restart_s; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd b/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd new file mode 100644 index 0000000..60c09f4 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd @@ -0,0 +1,149 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bram_reader_nt is + generic ( + MEM_DEPTH : natural := 1024; + MEM_AWIDTH : natural := 10; + AXIS_DWIDTH : natural := 16 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data_i : in std_logic_vector(16-1 downto 0); + sts_data_o : out std_logic_vector(16-1 downto 0); + done_i : in std_logic; + send_i : in std_logic; + restart_o : out std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0); + + -- BRAM port + bram_clk : out std_logic; + bram_rst : out std_logic; + bram_en : out std_logic; + bram_addr : out std_logic_vector(MEM_AWIDTH-1 downto 0); + bram_rddata : in std_logic_vector(AXIS_DWIDTH-1 downto 0) + ); +end bram_reader_nt; + +architecture rtl of bram_reader_nt is + + type state_t is ( + ST_IDLE, + ST_EN_BRAM, + ST_SEND_DATA, + ST_TLAST, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tlast_s, rst_s, en_s : std_logic; +signal tvalid_s : std_logic; +signal restart_s : std_logic; +signal tkeep_s : std_logic_vector(4-1 downto 0); +signal bram_st_mon : std_logic_vector(4-1 downto 0); + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + state_reg <= ST_IDLE; + addr_reg <= (others => '0'); + else + state_reg <= state_next; + addr_reg <= addr_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, addr_reg, done_i, send_i, m_axis_tready, + cfg_data_i) + begin + state_next <= state_reg; + addr_next <= addr_reg; + tvalid_s <= '0'; + tlast_s <= '0'; + restart_s <= '0'; + en_s <= '0'; + rst_s <= '0'; + tkeep_s <= (others => '0'); + + case state_reg is + when ST_IDLE => + bram_st_mon <= "0000"; --state mon + rst_s <= '1'; + addr_next <= (others => '0'); + if (done_i = '1') and (send_i = '1') then + state_next <= ST_EN_BRAM; + else + state_next <= ST_IDLE; + end if; + + when ST_EN_BRAM => + bram_st_mon <= "0001"; --state mon + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + state_next <= ST_SEND_DATA; + else + state_next <= ST_EN_BRAM; + end if; + + when ST_SEND_DATA => + bram_st_mon <= "0010"; --state mon + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + if (addr_reg = unsigned(cfg_data_i)-1) then + addr_next <= (others => '0'); + state_next <= ST_TLAST; + else + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + + when ST_TLAST => + bram_st_mon <= "0011"; + tvalid_s <= '1'; + tlast_s <= '1'; + state_next <= ST_FINISH; + + when ST_FINISH => + bram_st_mon <= "0100"; --state mon + restart_s <= '1'; + state_next <= ST_IDLE; + + end case; + end process; + + sts_data_o <= std_logic_vector(resize(addr_reg,16)); + + m_axis_tdata <= bram_rddata; + m_axis_tvalid <= tvalid_s; + m_axis_tlast <= tlast_s; + m_axis_tkeep <= tkeep_s; + + bram_clk <= aclk; + bram_rst <= rst_s; + bram_en <= en_s; + bram_addr <= std_logic_vector(addr_reg); + restart_o <= restart_s; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/core_config.tcl b/cores/axis_avgr32bits_v1_0/core_config.tcl new file mode 100644 index 0000000..18531b2 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/core_config.tcl @@ -0,0 +1,29 @@ +set display_name {AXI4-Stream Averager 32 bits v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter S_AXIS_DWIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter M_AXIS_DWIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.} +core_parameter ADC_DWIDTH {ADC DATA WIDTH} {Width of the ADC data.} +core_parameter MEM_AWIDTH {MEMORY ADDR WIDTH} {Address width of the data memory.} +core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces m_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter + diff --git a/cores/axis_avgr32bits_v1_0/edge_det.vhd b/cores/axis_avgr32bits_v1_0/edge_det.vhd new file mode 100644 index 0000000..11dfb19 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/edge_det.vhd @@ -0,0 +1,58 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity edge_det is + port( + aclk : in std_logic; + aresetn: in std_logic; + sig_i : in std_logic; + sig_o : out std_logic + ); +end edge_det; + +architecture rtl of edge_det is + type state_t is (zero, edge, one); + signal state_reg, state_next: state_t; +begin + -- state register + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + state_reg <= zero; + else + state_reg <= state_next; + end if; + end if; + end process; + + -- next-state logic + process(state_reg, sig_i) + begin + case state_reg is + when zero=> + if sig_i = '1' then + state_next <= edge; + else + state_next <= zero; + end if; + when edge => + if sig_i = '1' then + state_next <= one; + else + state_next <= zero; + end if; + when one => + if sig_i = '1' then + state_next <= one; + else + state_next <= zero; + end if; + end case; + end process; + + -- Moore output logic + sig_o <= '1' when state_reg=edge else + '0'; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/n_sync.vhd b/cores/axis_avgr32bits_v1_0/n_sync.vhd new file mode 100644 index 0000000..1a92e1d --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/n_sync.vhd @@ -0,0 +1,46 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity n_sync is + generic( + N : natural + ); + port( + aclk : in std_logic; + aresetn : in std_logic; + in_async : in std_logic_vector(N-1 downto 0); + out_sync : out std_logic_vector(N-1 downto 0) + ); +end n_sync; + +architecture two_ff_arch of n_sync is + signal meta_reg, meta_next : std_logic_vector(N-1 downto 0); + signal sync_reg, sync_next: std_logic_vector(N-1 downto 0); + + attribute ASYNC_REG : string; + attribute ASYNC_REG of meta_reg: signal is "TRUE"; + attribute ASYNC_REG of sync_reg: signal is "TRUE"; + +begin + + -- two registers + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + meta_reg <= (others=>'0'); + sync_reg <= (others=>'0'); + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr32bits_v1_0/old_stuffs/avg_ntoone.vhd b/cores/axis_avgr32bits_v1_0/old_stuffs/avg_ntoone.vhd new file mode 100644 index 0000000..82d5772 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/old_stuffs/avg_ntoone.vhd @@ -0,0 +1,256 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_ntoone is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 32; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + + --avg_o : out std_logic_vector(O_DWIDTH-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0) + ); +end avg_ntoone; + +architecture rtl of avg_ntoone is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_AVG_N1, + ST_WRITE_AVG, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tdp_dia : std_logic_vector(O_DWIDTH-1 downto 0); +signal tdp_doa : std_logic_vector(O_DWIDTH-1 downto 0); +signal data_reg, data_next : std_logic_vector(2*I_DWIDTH-1 downto 0); +signal samples_reg, samples_next : unsigned(ADC_DWIDTH-1 downto 0); + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0); +signal restart_s, restart_os : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0); +signal naverages_b : std_logic_vector(O_DWIDTH-1 downto 0); + +begin + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => MEM_AWIDTH, + DWIDTH => O_DWIDTH + ) + port map( + clka => s_axis_aclk, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia, + + clkb => bram_clk, + rstb => bram_rst, + enb => bram_en, + addrb => bram_addr, + dob => bram_rddata + ); + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + tdp_addra_reg <= (others => '0'); + data_reg <= (others => '0'); + samples_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + tdp_addra_reg <= tdp_addra_next; + data_reg <= data_next; + samples_reg <= samples_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, en_i, start_i, trig_i, nsamples_i, + naverages_i, tdp_addra_reg, tdp_dia, data_reg, samples_reg, + s_axis_tvalid, s_axis_tdata, avg_reg, m_axis_tready, restart_os) + variable dinbv : std_logic_vector(O_DWIDTH-1 downto 0); + begin + state_next <= state_reg; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + data_next <= data_reg; + samples_next <= samples_reg; + tdp_dia <= (others => '0'); + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + --state_mon <= "0000"; --state mon + samples_next <= (others => '0'); + tdp_addra_next <= (others => '0'); + avg_next <= (others => '0'); + data_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + --state_mon <= "0001"; --state mon + if(trig_i = '1') then + state_next <= ST_AVG_N1; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_AVG_N1 => + --state_mon <= "0010"; + if (s_axis_tvalid = '1') then + tready_s <= '1'; + samples_next <= samples_reg + 1; + ASSIGN_N: for I in 0 to RATIO-1 loop + data_next(2*I_DWIDTH-1-I*2*ADC_DWIDTH downto 2*I_DWIDTH-(I+1)*2*ADC_DWIDTH) <= + std_logic_vector(signed(data_reg(2*I_DWIDTH-1-I*2*ADC_DWIDTH downto 2*I_DWIDTH-(I+1)*2*ADC_DWIDTH)) + + resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH))),ADC_DWIDTH)); + end loop; + if(samples_reg = (unsigned(nsamples_i)/RATIO)-1) then + samples_next <= (others => '0'); + state_next <= ST_WRITE_AVG; + end if; + end if; + + when ST_WRITE_AVG => + --state_mon <= "0011"; + dinbv := (others => '0'); + ASSIGN_AVG1: for K in 0 to RATIO-1 loop + dinbv := std_logic_vector(signed(dinbv) + signed(data_reg(2*I_DWIDTH-1-K*2*ADC_DWIDTH downto 2*I_DWIDTH-(K+1)*2*ADC_DWIDTH))); + end loop; + tdp_dia <= dinbv; + tdp_wea <= '1'; + data_next <= (others => '0'); + tdp_addra_next <= tdp_addra_reg + 1; + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_FINISH => + --state_mon <= "0100"; + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_IDLE; + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_nt: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + naverages_b <= (31 downto 16 => '0') & naverages_i; + reader_i: entity work.bram_reader + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => naverages_b, + --cfg_data_i => naverages_i, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/old_stuffs/avg_scope.vhd b/cores/axis_avgr32bits_v1_0/old_stuffs/avg_scope.vhd new file mode 100644 index 0000000..eca402c --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/old_stuffs/avg_scope.vhd @@ -0,0 +1,365 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity avg_scope is + generic ( + I_DWIDTH : natural := 128; -- ADC data width x8 + O_DWIDTH : natural := 32; -- AXI data width + ADC_DWIDTH : natural := 16; -- ADC data width + MEM_AWIDTH : natural := 10; -- + MEM_DEPTH : natural := 1024 -- Max 2**16 + ); + port ( + -- Averager specific ports + start_i : in std_logic; + send_i : in std_logic; + trig_i : in std_logic; + done_o : out std_logic; + --state_mon : out std_logic_vector(3 downto 0); + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + en_i : in std_logic; + naverages_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + nsamples_i : in std_logic_vector(ADC_DWIDTH-1 downto 0); + + --bram_en_o : out std_logic; + --bram_addr_o : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_o : out std_logic_vector(O_DWIDTH-1 downto 0); + --bram_en_oo : out std_logic; + --bram_addr_oo : out std_logic_vector(MEM_AWIDTH-1 downto 0); + --bram_rddata_oo : out std_logic_vector(O_DWIDTH-1 downto 0); + --avg_o : out std_logic_vector(O_DWIDTH-1 downto 0); + + --tdp_addra_o : out std_logic_vector(11-1 downto 0); + --tdp_addrb_o : out std_logic_vector(11-1 downto 0); + + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn : in std_logic; + + -- Slave side + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(I_DWIDTH-1 downto 0); + + -- Master side + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(O_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0) + ); +end avg_scope; + +architecture rtl of avg_scope is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := I_DWIDTH/ADC_DWIDTH; + + type state_t is ( + ST_IDLE, + ST_WAIT_TRIG, + ST_EN_TDPB, + ST_AVG_SCOPE, + ST_FINISH, + ST_WR_ZEROS +); +signal state_reg, state_next : state_t; +--signal state_mon_reg, state_mon_next : std_logic_vector(3 downto 0); + +signal rstb_s : std_logic; +signal tdp_wea : std_logic; +signal tdp_addra_reg, tdp_addra_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal tdp_dia : std_logic_vector(2*I_DWIDTH-1 downto 0); +signal tdp_enb : std_logic; +signal tdp_addrb_reg, tdp_addrb_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal tdp_doa, tdp_dob : std_logic_vector(2*I_DWIDTH-1 downto 0); +signal addrb_s : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); + +signal asy_rsta : std_logic; +signal asy_ena : std_logic; +signal asy_enb : std_logic; +signal asy_web : std_logic; +signal asy_doa : std_logic_vector(ADC_DWIDTH-1 downto 0); + +signal done_s, tready_s : std_logic; +signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0); +signal restart_s, restart_os : std_logic; + +signal bram_clk : std_logic; +signal bram_rst : std_logic; +signal bram_en : std_logic; +signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0); +signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0); +signal nsamples_b : std_logic_vector(O_DWIDTH-1 downto 0); + +begin + + --state_mon <= state_mon_reg; + --tdp_addra_o <= std_logic_vector(tdp_addra_reg); + --tdp_addrb_o <= std_logic_vector(tdp_addrb_reg); + + s_axis_tready <= tready_s; + --avg_o <= std_logic_vector(avg_reg); + done_o <= done_s; + + -- TDP RAM + tdp_ram_i : entity work.tdp_ram_pip + generic map( + AWIDTH => log2c(MEM_DEPTH/RATIO), + DWIDTH => 2*I_DWIDTH + ) + port map( + clka => s_axis_aclk, + --rsta => rsta_s, + wea => tdp_wea, + addra => std_logic_vector(tdp_addra_reg), + dia => tdp_dia, + + clkb => s_axis_aclk, + rstb => rstb_s, + enb => tdp_enb, --'1', + addrb => std_logic_vector(tdp_addrb_reg), + dob => tdp_dob + ); + + -- ASYMMETRIC RAM + -- Port A -> AXI IF + -- Port B -> same as WIDER BRAM + asy_ram_i : entity work.asym_ram_sdp_write_wider + generic map + ( + WIDTHA => O_DWIDTH, + SIZEA => MEM_DEPTH, + ADDRWIDTHA => MEM_AWIDTH, + WIDTHB => 2*I_DWIDTH, + SIZEB => (MEM_DEPTH/RATIO), + ADDRWIDTHB => log2c(MEM_DEPTH/RATIO) + ) + port map + ( + clkA => bram_clk, + rstA => bram_rst, + enA => bram_en, + addrA => bram_addr, + doA => bram_rddata, + + --portB same as portA in tdp_ram + clkB => s_axis_aclk, + weB => tdp_wea, + addrB => std_logic_vector(tdp_addra_reg), + diB => tdp_dia + ); + + --debug signals + --lets synchronize the en signal + --sync_bram_en: entity work.sync + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_en, + -- out_sync => bram_en_o + -- ); + --bram_en_oo <= bram_en; + + --lets synchronize the addr signal + --sync_bram_addr: entity work.n_sync + --generic map( + -- N => MEM_AWIDTH + -- ) + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_addr, + -- out_sync => bram_addr_o + -- ); + --bram_addr_oo <= bram_addr; + + ----lets synchronize the en signal + --sync_bram_rddata: entity work.n_sync + --generic map( + -- N => O_DWIDTH + -- ) + --port map( + -- aclk => s_axis_aclk, + -- aresetn => s_axis_aresetn, + -- in_async => bram_rddata, + -- out_sync => bram_rddata_o + -- ); + --bram_rddata_oo <= bram_rddata; + + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + state_reg <= ST_IDLE; + --state_mon_reg <= (others => '0'); + tdp_addra_reg <= (others => '0'); + tdp_addrb_reg <= (others => '0'); + avg_reg <= (others => '0'); + else + state_reg <= state_next; + --state_mon_reg <= state_mon_next; + tdp_addra_reg <= tdp_addra_next; + tdp_addrb_reg <= tdp_addrb_next; + avg_reg <= avg_next; + end if; + end if; + end process; + + --tdp_addra_next <= tdp_addrb_reg; + + --Next state logic + --process(state_reg, state_mon_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, + process(state_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, + tdp_addra_reg, tdp_addrb_reg, tdp_dia, tdp_dob, s_axis_tvalid, s_axis_tdata, + avg_reg, m_axis_tready, restart_os) + begin + state_next <= state_reg; + --state_mon_next<= state_mon_reg; + rstb_s <= '0'; + tdp_wea <= '0'; + tdp_addra_next<= tdp_addra_reg; + tdp_dia <= (others => '0'); + tdp_enb <= '0'; + tdp_addrb_next<= tdp_addrb_reg; + asy_rsta <= '1'; + asy_ena <= '0'; + tready_s <= '0'; + avg_next <= avg_reg; + done_s <= '0'; + + case state_reg is + when ST_IDLE => -- Start + rstb_s <= '1'; + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= (others => '0'); + if en_i = '1' and start_i = '1' then + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + else + state_next <= ST_IDLE; + --state_mon_next <= (others => '0'); + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + if(trig_i = '1') then + state_next <= ST_EN_TDPB; + --state_mon_next <= "0010"; + else + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + end if; + + when ST_EN_TDPB => + if (s_axis_tvalid = '1') then + tdp_enb <= '1'; + tdp_addrb_next <= tdp_addrb_reg + 1; + state_next <= ST_AVG_SCOPE; + --state_mon_next <= "0011"; + end if; + + when ST_AVG_SCOPE => -- Measure + if (s_axis_tvalid = '1') then + tready_s <= '1'; + tdp_enb <= '1'; + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + tdp_addrb_next <= tdp_addrb_reg + 1; + ASSIGN_G1: for I in 0 to RATIO-1 loop + tdp_dia(2*I_DWIDTH-1-I*2*ADC_DWIDTH downto 2*I_DWIDTH-(I+1)*2*ADC_DWIDTH) <= + std_logic_vector(signed(tdp_dob(2*I_DWIDTH-1-I*2*ADC_DWIDTH downto 2*I_DWIDTH-(I+1)*2*ADC_DWIDTH)) + + resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH))),O_DWIDTH)); + end loop; + if(tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + tdp_addra_next <= (others => '0'); + tdp_addrb_next <= (others => '0'); + avg_next <= avg_reg + 1; + if (avg_reg = unsigned(naverages_i)-1) then + state_next <= ST_FINISH; + --state_mon_next <= "0100"; + else + state_next <= ST_WAIT_TRIG; + --state_mon_next <= "0001"; + end if; + end if; + else + state_next <= ST_AVG_SCOPE; + --state_mon_next <= "0011"; + end if; + + when ST_FINISH => + done_s <= '1'; + if restart_os = '1' then + state_next <= ST_WR_ZEROS; + --state_mon_next <= "0101"; + end if; + + when ST_WR_ZEROS => + tdp_wea <= '1'; + tdp_addra_next <= tdp_addra_reg + 1; + if (tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then + state_next <= ST_IDLE; + --state_mon_next <= (others => '0'); + end if; + + end case; + end process; + + --lets synchronize the restart signal + os_restart_as: entity work.edge_det + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + sig_i => restart_s, + sig_o => restart_os + ); + + nsamples_b <= (31 downto 16 => '0') & nsamples_i; + reader_i: entity work.bram_reader + generic map( + MEM_DEPTH => MEM_DEPTH, + MEM_AWIDTH => MEM_AWIDTH, + AXIS_DWIDTH => O_DWIDTH + ) + port map( + + cfg_data_i => nsamples_b, + --cfg_data_i => nsamples_i, + --sts_data_o => open, + done_i => done_s, + send_i => send_i, + restart_o => restart_s, + + -- Master side + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + m_axis_tkeep => m_axis_tkeep, + -- BRAM port + bram_clk => bram_clk, + bram_rst => bram_rst, + bram_en => bram_en, + bram_addr => bram_addr, + bram_rddata => bram_rddata + ); + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/old_stuffs/bram_reader.vhd b/cores/axis_avgr32bits_v1_0/old_stuffs/bram_reader.vhd new file mode 100644 index 0000000..8b9376b --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/old_stuffs/bram_reader.vhd @@ -0,0 +1,150 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bram_reader is + generic ( + MEM_DEPTH : natural := 1024; + MEM_AWIDTH : natural := 10; + AXIS_DWIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data_i : in std_logic_vector(AXIS_DWIDTH-1 downto 0); + --sts_data_o : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + done_i : in std_logic; + send_i : in std_logic; + restart_o : out std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_DWIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tkeep : out std_logic_vector(4-1 downto 0); + + -- BRAM port + bram_clk : out std_logic; + bram_rst : out std_logic; + bram_en : out std_logic; + bram_addr : out std_logic_vector(MEM_AWIDTH-1 downto 0); + bram_rddata : in std_logic_vector(AXIS_DWIDTH-1 downto 0) + ); +end bram_reader; + +architecture rtl of bram_reader is + + type state_t is ( + ST_IDLE, + ST_EN_BRAM, + ST_SEND_DATA, + ST_TLAST, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : unsigned(MEM_AWIDTH-1 downto 0); +signal tlast_s, rst_s, en_s : std_logic; +signal tvalid_s : std_logic; +signal restart_s : std_logic; +signal tkeep_s : std_logic_vector(4-1 downto 0); +--signal bram_st_mon : std_logic_vector(4-1 downto 0); + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + state_reg <= ST_IDLE; + addr_reg <= (others => '0'); + else + state_reg <= state_next; + addr_reg <= addr_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, addr_reg, done_i, send_i, m_axis_tready, + cfg_data_i) + begin + state_next <= state_reg; + addr_next <= addr_reg; + tvalid_s <= '0'; + tlast_s <= '0'; + restart_s <= '0'; + en_s <= '0'; + rst_s <= '0'; + tkeep_s <= (others => '0'); + + case state_reg is + when ST_IDLE => + --bram_st_mon <= "0000"; --state mon + rst_s <= '1'; + addr_next <= (others => '0'); + if (done_i = '1') and (send_i = '1') then + state_next <= ST_EN_BRAM; + else + state_next <= ST_IDLE; + end if; + + when ST_EN_BRAM => + --bram_st_mon <= "0001"; --state mon + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + state_next <= ST_SEND_DATA; + else + state_next <= ST_EN_BRAM; + end if; + + when ST_SEND_DATA => + --bram_st_mon <= "0010"; --state mon + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + if m_axis_tready = '1' then + en_s <= '1'; + addr_next <= addr_reg + 1; + if (addr_reg = unsigned(cfg_data_i)-1) then + --addr_next <= (others => '0'); + state_next <= ST_TLAST; + else + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + + when ST_TLAST => + --bram_st_mon <= "0011"; + tvalid_s <= '1'; + tkeep_s <= (others => '1'); + tlast_s <= '1'; + state_next <= ST_FINISH; + + when ST_FINISH => + --bram_st_mon <= "0100"; --state mon + restart_s <= '1'; + state_next <= ST_IDLE; + + end case; + end process; + + --sts_data_o <= std_logic_vector(resize(addr_reg,AXIS_DWIDTH)); + + m_axis_tdata <= bram_rddata; + m_axis_tvalid <= tvalid_s; + m_axis_tlast <= tlast_s; + m_axis_tkeep <= tkeep_s; + + bram_clk <= aclk; + bram_rst <= rst_s; + bram_en <= en_s; + bram_addr <= std_logic_vector(addr_reg); + restart_o <= restart_s; + +end rtl; diff --git a/cores/axis_avgr32bits_v1_0/sync.vhd b/cores/axis_avgr32bits_v1_0/sync.vhd new file mode 100644 index 0000000..492bcf6 --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/sync.vhd @@ -0,0 +1,43 @@ +library ieee; +use ieee.std_logic_1164.all; + +--synchronizer +entity sync is + port( + aclk : in std_logic; + aresetn : in std_logic; + in_async : in std_logic; + out_sync : out std_logic + ); +end sync; + +architecture two_ff_arch of sync is + signal meta_reg, meta_next : std_logic; + signal sync_reg, sync_next: std_logic; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of meta_reg: signal is "TRUE"; + attribute ASYNC_REG of sync_reg: signal is "TRUE"; +begin + + -- two registers + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn='0') then + meta_reg <= '0'; + sync_reg <= '0'; + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd b/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd new file mode 100644 index 0000000..712f43a --- /dev/null +++ b/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd @@ -0,0 +1,86 @@ +-- Block RAM with Optional Output Registers +-- File: modified from rams_pipeline.vhd +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity tdp_ram_pip is + generic ( + AWIDTH : integer := 16; + DWIDTH : integer := 16 + ); + port( + clka : in std_logic; + --rsta : in std_logic; + --ena : in std_logic; + wea : in std_logic; + addra : in std_logic_vector(AWIDTH-1 downto 0); + dia : in std_logic_vector(DWIDTH-1 downto 0); + --doa : out std_logic_vector(DWIDTH-1 downto 0); + clkb : in std_logic; + rstb : in std_logic; + enb : in std_logic; + --web : in std_logic; + addrb : in std_logic_vector(AWIDTH-1 downto 0); + --dib : in std_logic_vector(DWIDTH-1 downto 0); + dob : out std_logic_vector(DWIDTH-1 downto 0) + ); +end tdp_ram_pip; + +architecture rtl of tdp_ram_pip is + type ram_t is array (0 to 2**AWIDTH-1) of std_logic_vector(DWIDTH-1 downto 0); + signal ram : ram_t := (others => (others => '0')); + signal a_reg, a_next : std_logic_vector(DWIDTH-1 downto 0); + signal b_reg, b_next : std_logic_vector(DWIDTH-1 downto 0); + +begin + + process(clka) + begin + if rising_edge(clka) then + if wea = '1' then + ram(to_integer(unsigned(addra))) <= dia; + end if; + --do1 <= ram(to_integer(unsigned(addra))); + end if; + end process; + + --process(clka) + --begin + -- if rising_edge(clka) then + -- if rsta = '1' then + -- a_reg <= (others => '0'); + -- else + -- a_reg <= a_next; + -- end if; + -- end if; + --end process; + ----next state logic + --a_next <= ram(to_integer(unsigned(addra))) when ena = '1' else a_reg; + --doa <= a_reg; + + --process(clkb) + --begin + -- if rising_edge(clkb) then + -- if web = '1' then + -- ram(to_integer(unsigned(addrb))) <= dib; + -- end if; + -- --do2 <= ram(to_integer(unsigned(addrb))); + -- end if; + --end process; + + process(clkb) + begin + if rising_edge(clkb) then + if rstb = '1' then + b_reg <= (others => '0'); + else + b_reg <= b_next; + end if; + end if; + end process; + --next state logic + b_next <= ram(to_integer(unsigned(addrb))) when enb = '1' else b_reg; + dob <= b_reg; + +end rtl; diff --git a/cores/axis_avgr_v1_0/asym_ram_tdp.vhd b/cores/axis_avgr_v1_0/asym_ram_tdp.vhd new file mode 100644 index 0000000..cd074ff --- /dev/null +++ b/cores/axis_avgr_v1_0/asym_ram_tdp.vhd @@ -0,0 +1,115 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity asym_ram_tdp is + generic ( + WIDTHA : integer := 4; + --SIZEA : integer := 1024; + ADDRWIDTHA : integer := 10; + WIDTHB : integer := 16; + --SIZEB : integer := 256; + ADDRWIDTHB : integer := 8 + ); + port ( + clka : in std_logic; + clkb : in std_logic; + ena : in std_logic; + enb : in std_logic; + wea : in std_logic; + web : in std_logic; + addra : in std_logic_vector(ADDRWIDTHA-1 downto 0); + addrb : in std_logic_vector(ADDRWIDTHB-1 downto 0); + dia : in std_logic_vector(WIDTHA-1 downto 0); + dib : in std_logic_vector(WIDTHB-1 downto 0); + doa : out std_logic_vector(WIDTHA-1 downto 0); + dob : out std_logic_vector(WIDTHB-1 downto 0) + ); +end asym_ram_tdp; + + +architecture asym_ram_tdp_arc of asym_ram_tdp is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + function log2 (val: INTEGER) return natural is + variable res : natural; + begin + for i in 0 to 31 loop + if (val <= (2**i)) then + res := i; + exit; + end if; + end loop; + return res; + end function log2; + + constant SIZEA : integer := 2**ADDRWIDTHA; + constant SIZEB : integer := 2**ADDRWIDTHB; + constant minWIDTH : integer := min(WIDTHA,WIDTHB); + constant maxWIDTH : integer := max(WIDTHA,WIDTHB); + constant maxSIZE : integer := max(SIZEA,SIZEB); + constant RATIO : integer := maxWIDTH / minWIDTH; + + -- An asymmetric RAM is modeled in a similar way as a symmetric RAM, with an + -- array of array object. Its aspect ratio corresponds to the port with the lower + -- data width (larger depth). + type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0); + + shared variable ram : ramType := (others => (others => '0')); + + signal readA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); + signal readB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); + signal regA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); + signal regB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); + +begin + + process (clka) + begin + if rising_edge(clka) then + if ena = '1' then + readA <= ram(to_integer(unsigned(addra))); + if wea = '1' then + ram(to_integer(unsigned(addra))) := dia; + end if; + end if; + regA <= readA; + end if; + end process; + + process (clkb) + begin + if rising_edge(clkb) then + for i in 0 to RATIO-1 loop + if enb = '1' then + readB((i+1)*minWIDTH-1 downto i*minWIDTH) <= ram(to_integer(unsigned(addrb) & to_unsigned(i,log2(RATIO)))); + if web = '1' then + ram(to_integer(unsigned(addrb) & to_unsigned(i,log2(RATIO)))) := dib((i+1)*minWIDTH-1 downto i*minWIDTH); + end if; + end if; + end loop; + regB <= readB; + end if; + end process; + + doa <= regA; + dob <= regB; + +end asym_ram_tdp_arc; diff --git a/cores/axis_avgr_v1_0/averager.vhd b/cores/axis_avgr_v1_0/averager.vhd new file mode 100644 index 0000000..1498733 --- /dev/null +++ b/cores/axis_avgr_v1_0/averager.vhd @@ -0,0 +1,330 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity averager is + generic ( + IN_DATA_WIDTH : natural := 128; -- ADC data width x8 + OUT_DATA_WIDTH : natural := 32; -- AXI data width + ADC_DATA_WIDTH : natural := 16; -- ADC data width + MEM_DEPTH : natural := 10 -- Max 2**16 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + -- Averager specific ports + start : in std_logic; + restart : in std_logic; + mode : in std_logic; --0- (default) avg scope, 1-avg nsamples to one value + trig_i : in std_logic; + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + nsamples : in std_logic_vector(32-1 downto 0); + naverages : in std_logic_vector(32-1 downto 0); + done : out std_logic; + averages_out : out std_logic_vector(32-1 downto 0); + -- BRAM PORTA. Reading port + bram_porta_clk : in std_logic; + --bram_porta_rst : in std_logic; + bram_porta_wrdata : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + bram_porta_we : in std_logic; + bram_porta_addr : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + bram_porta_rddata : out std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(IN_DATA_WIDTH-1 downto 0) + ); +end averager; + +architecture rtl of averager is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := IN_DATA_WIDTH/ADC_DATA_WIDTH; + constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH); + + type state_t is ( +-- ST_WRITE_ZEROS, + ST_IDLE, + ST_WRITE_ZEROS, + ST_WAIT_TRIG, + ST_AVG_SCOPE, + ST_AVG_N1, + ST_WRITE_AVG, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal addr_dly_reg, addr_dly_next: std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal data_reg, data_next : std_logic_vector(IN_DATA_WIDTH-1 downto 0); +signal tready_reg, tready_next : std_logic; + +signal averages_reg, averages_next: std_logic_vector(32-1 downto 0); +signal done_reg, done_next : std_logic; +signal dout_b_s : std_logic_vector(IN_DATA_WIDTH-1 downto 0); +signal addr_s : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0); +signal brama_clk, bramb_clk : std_logic; +--signal brama_rst, bramb_rst : std_logic; +signal bramb_out : std_logic_vector(ADC_DATA_WIDTH-1 downto 0); +signal dinb_reg, dinb_next : std_logic_vector(ADC_DATA_WIDTH-1 downto 0); +signal addrb_s : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0); +signal wren_reg, wren_next : std_logic; +signal wrenb_reg, wrenb_next : std_logic; +signal web : std_logic; + +begin + + BUFGMUX_inst: BUFGMUX + port map ( + O => brama_clk, -- 1-bit output: Clock output + I0 => aclk, -- 1-bit input: Clock input (S=0) + I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1) + S => done_reg -- 1-bit input: Clock select + ); + + s_axis_tready <= tready_reg; + done <= done_reg; + averages_out <= averages_reg; + addr_dly_next <= addr_reg; + addr_s <= std_logic_vector(resize(unsigned(unsigned(bram_porta_addr)-1),addrb_s'length)) when (done_reg = '1') else + std_logic_vector(resize(unsigned(unsigned(averages_reg)-1),addrb_s'length)); + web <= wren_reg when (mode = '0') else '0'; + --bram_porta_rddata <= std_logic_vector(resize(unsigned(bramb_out),bram_porta_rddata'length)) when (done_reg = '1') else (others => '0'); + bram_porta_rddata <= std_logic_vector(resize(signed(bramb_out),bram_porta_rddata'length)); + -- brama_rst <= bram_porta_rst when (done_reg = '1') and (mode = '0') else + -- aresetn; + + -- DP RAM + tdp_ram_i : entity work.tdp_bram + generic map( + AWIDTH => log2c(MEM_DEPTH/RATIO), + DWIDTH => IN_DATA_WIDTH + ) + port map( + clka => aclk, + clkb => aclk, + ena => '1', + enb => '1', + wea => wren_reg, + web => '0', + addra => addr_dly_reg, + addrb => addr_reg, + dia => data_reg, + dib => (others => '0'), + doa => open, + dob => dout_b_s + ); + + -- ASYMMETRIC RAM + -- Port A -> AXI IF + -- Port B -> same as WIDER BRAM + ram_asy : entity work.asym_ram_tdp + generic map + ( + WIDTHA => ADC_DATA_WIDTH, + ADDRWIDTHA => log2c(MEM_DEPTH), + WIDTHB => IN_DATA_WIDTH, + ADDRWIDTHB => log2c(MEM_DEPTH/RATIO) + ) + port map + ( + --portA same as op_ram + clka => brama_clk, + ena => '1', + wea => wrenb_reg, + addra => addr_s, + dia => dinb_reg, + doa => bramb_out, + + --portB same as portA in dp_ram + clkb => aclk, --brama_clk, + enb => '1', + web => web, --wren_reg, + addrb => addr_dly_reg, + dib => data_reg, + dob => open + ); + + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + --state_reg <= ST_WRITE_ZEROS; + addr_reg <= (others => '0'); + addr_dly_reg <= (others => '0'); + data_reg <= (others => '0'); + averages_reg <= (others => '0'); + dinb_reg <= (others => '0'); + tready_reg <= '0'; + done_reg <= '0'; + wren_reg <= '0'; + wrenb_reg <= '0'; + else + state_reg <= state_next; + addr_reg <= addr_next; + addr_dly_reg <= addr_dly_next; + data_reg <= data_next; + dinb_reg <= dinb_next; + averages_reg <= averages_next; + tready_reg <= tready_next; + done_reg <= done_next; + wren_reg <= wren_next; + wrenb_reg <= wrenb_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, start, mode, trig_i, restart, nsamples, naverages, addr_reg, s_axis_tvalid) + variable dinbv : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0'); + begin + state_next <= state_reg; + addr_next <= addr_reg; + data_next <= data_reg; + averages_next <= averages_reg; + wren_next <= wren_reg; + wrenb_next <= wrenb_reg; + tready_next <= tready_reg; + done_next <= done_reg; + dinb_next <= dinb_reg; + dinbv := (others => '0'); + + case state_reg is + --when ST_WRITE_ZEROS => -- Clear BRAM state one time case + -- wren_next <= '1'; + -- wrenb_next <= '1'; + -- addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + -- if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + -- wren_next <= '0'; + -- wrenb_next <= '0'; + -- addr_next <= (others => '0'); + -- state_next <= ST_IDLE; + -- end if; + + when ST_IDLE => -- Start + addr_next <= (others => '0'); + data_next <= (others => '0'); + averages_next <= (others => '0'); + wren_next <= '0'; + wrenb_next <= '0'; + tready_next <= '0'; + done_next <= '0'; + dinb_next <= (others => '0'); + if start = '1' then + state_next <= ST_WRITE_ZEROS; + --state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WRITE_ZEROS => -- Clear BRAM state + wren_next <= '1'; + wrenb_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if(unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + wren_next <= '0'; + wrenb_next <= '0'; + addr_next <= (others => '0'); + state_next <= ST_WAIT_TRIG; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + --wrenb_next <= '0'; + if(trig_i = '1') and (s_axis_tvalid = '1') then + tready_next <= '1'; + if (mode = '0') then + state_next <= ST_AVG_SCOPE; + else + state_next <= ST_AVG_N1; + end if; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_AVG_SCOPE => -- Measure + --ASSIGN_G: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_G: for I in 0 to RATIO-1 loop + data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= + std_logic_vector(signed(dout_b_s(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + + signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH))); + end loop; + wren_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + averages_next <= std_logic_vector(unsigned(averages_reg) + 1); + addr_next <= (others => '0'); + tready_next <= '0'; + wren_next <= '0'; + if (unsigned(averages_reg) = unsigned(naverages)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + end if; + + when ST_AVG_N1 => -- N to 1 average + --ASSIGN_N: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_N: for I in 0 to RATIO-1 loop + data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= + std_logic_vector(signed(data_reg(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + + signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH))); + end loop; + wren_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + averages_next <= std_logic_vector(unsigned(averages_reg) + 1); + addr_next <= (others => '0'); + tready_next <= '0'; + wren_next <= '0'; + --ASSIGN_AVG: for K in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_AVG: for K in 0 to RATIO-1 loop + dinbv := + std_logic_vector(signed(dinbv) + signed(data_reg(IN_DATA_WIDTH-1-K*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(K+1)*ADC_DATA_WIDTH))); + end loop; + dinb_next <= dinbv; + wrenb_next <= '1'; + if (unsigned(averages_reg) = unsigned(naverages)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WRITE_AVG; + end if; + end if; + + when ST_WRITE_AVG => -- write bramb + wrenb_next <= '0'; + data_next <= (others => '0'); + state_next <= ST_WAIT_TRIG; + + when ST_FINISH => -- done + wrenb_next <= '0'; + done_next <= '1'; + if restart = '1' then + --wren_next <= '1'; + --data_next <= (others => '0'); + state_next <= ST_IDLE; + end if; + end case; + end process; + +end rtl; diff --git a/cores/axis_avgr_v1_0/averager.vhd_bkp b/cores/axis_avgr_v1_0/averager.vhd_bkp new file mode 100644 index 0000000..1498733 --- /dev/null +++ b/cores/axis_avgr_v1_0/averager.vhd_bkp @@ -0,0 +1,330 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity averager is + generic ( + IN_DATA_WIDTH : natural := 128; -- ADC data width x8 + OUT_DATA_WIDTH : natural := 32; -- AXI data width + ADC_DATA_WIDTH : natural := 16; -- ADC data width + MEM_DEPTH : natural := 10 -- Max 2**16 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + -- Averager specific ports + start : in std_logic; + restart : in std_logic; + mode : in std_logic; --0- (default) avg scope, 1-avg nsamples to one value + trig_i : in std_logic; + --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW + nsamples : in std_logic_vector(32-1 downto 0); + naverages : in std_logic_vector(32-1 downto 0); + done : out std_logic; + averages_out : out std_logic_vector(32-1 downto 0); + -- BRAM PORTA. Reading port + bram_porta_clk : in std_logic; + --bram_porta_rst : in std_logic; + bram_porta_wrdata : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + bram_porta_we : in std_logic; + bram_porta_addr : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + bram_porta_rddata : out std_logic_vector(OUT_DATA_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(IN_DATA_WIDTH-1 downto 0) + ); +end averager; + +architecture rtl of averager is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant RATIO : natural := IN_DATA_WIDTH/ADC_DATA_WIDTH; + constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH); + + type state_t is ( +-- ST_WRITE_ZEROS, + ST_IDLE, + ST_WRITE_ZEROS, + ST_WAIT_TRIG, + ST_AVG_SCOPE, + ST_AVG_N1, + ST_WRITE_AVG, + ST_FINISH +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal addr_dly_reg, addr_dly_next: std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0); +signal data_reg, data_next : std_logic_vector(IN_DATA_WIDTH-1 downto 0); +signal tready_reg, tready_next : std_logic; + +signal averages_reg, averages_next: std_logic_vector(32-1 downto 0); +signal done_reg, done_next : std_logic; +signal dout_b_s : std_logic_vector(IN_DATA_WIDTH-1 downto 0); +signal addr_s : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0); +signal brama_clk, bramb_clk : std_logic; +--signal brama_rst, bramb_rst : std_logic; +signal bramb_out : std_logic_vector(ADC_DATA_WIDTH-1 downto 0); +signal dinb_reg, dinb_next : std_logic_vector(ADC_DATA_WIDTH-1 downto 0); +signal addrb_s : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0); +signal wren_reg, wren_next : std_logic; +signal wrenb_reg, wrenb_next : std_logic; +signal web : std_logic; + +begin + + BUFGMUX_inst: BUFGMUX + port map ( + O => brama_clk, -- 1-bit output: Clock output + I0 => aclk, -- 1-bit input: Clock input (S=0) + I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1) + S => done_reg -- 1-bit input: Clock select + ); + + s_axis_tready <= tready_reg; + done <= done_reg; + averages_out <= averages_reg; + addr_dly_next <= addr_reg; + addr_s <= std_logic_vector(resize(unsigned(unsigned(bram_porta_addr)-1),addrb_s'length)) when (done_reg = '1') else + std_logic_vector(resize(unsigned(unsigned(averages_reg)-1),addrb_s'length)); + web <= wren_reg when (mode = '0') else '0'; + --bram_porta_rddata <= std_logic_vector(resize(unsigned(bramb_out),bram_porta_rddata'length)) when (done_reg = '1') else (others => '0'); + bram_porta_rddata <= std_logic_vector(resize(signed(bramb_out),bram_porta_rddata'length)); + -- brama_rst <= bram_porta_rst when (done_reg = '1') and (mode = '0') else + -- aresetn; + + -- DP RAM + tdp_ram_i : entity work.tdp_bram + generic map( + AWIDTH => log2c(MEM_DEPTH/RATIO), + DWIDTH => IN_DATA_WIDTH + ) + port map( + clka => aclk, + clkb => aclk, + ena => '1', + enb => '1', + wea => wren_reg, + web => '0', + addra => addr_dly_reg, + addrb => addr_reg, + dia => data_reg, + dib => (others => '0'), + doa => open, + dob => dout_b_s + ); + + -- ASYMMETRIC RAM + -- Port A -> AXI IF + -- Port B -> same as WIDER BRAM + ram_asy : entity work.asym_ram_tdp + generic map + ( + WIDTHA => ADC_DATA_WIDTH, + ADDRWIDTHA => log2c(MEM_DEPTH), + WIDTHB => IN_DATA_WIDTH, + ADDRWIDTHB => log2c(MEM_DEPTH/RATIO) + ) + port map + ( + --portA same as op_ram + clka => brama_clk, + ena => '1', + wea => wrenb_reg, + addra => addr_s, + dia => dinb_reg, + doa => bramb_out, + + --portB same as portA in dp_ram + clkb => aclk, --brama_clk, + enb => '1', + web => web, --wren_reg, + addrb => addr_dly_reg, + dib => data_reg, + dob => open + ); + + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + --state_reg <= ST_WRITE_ZEROS; + addr_reg <= (others => '0'); + addr_dly_reg <= (others => '0'); + data_reg <= (others => '0'); + averages_reg <= (others => '0'); + dinb_reg <= (others => '0'); + tready_reg <= '0'; + done_reg <= '0'; + wren_reg <= '0'; + wrenb_reg <= '0'; + else + state_reg <= state_next; + addr_reg <= addr_next; + addr_dly_reg <= addr_dly_next; + data_reg <= data_next; + dinb_reg <= dinb_next; + averages_reg <= averages_next; + tready_reg <= tready_next; + done_reg <= done_next; + wren_reg <= wren_next; + wrenb_reg <= wrenb_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, start, mode, trig_i, restart, nsamples, naverages, addr_reg, s_axis_tvalid) + variable dinbv : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0'); + begin + state_next <= state_reg; + addr_next <= addr_reg; + data_next <= data_reg; + averages_next <= averages_reg; + wren_next <= wren_reg; + wrenb_next <= wrenb_reg; + tready_next <= tready_reg; + done_next <= done_reg; + dinb_next <= dinb_reg; + dinbv := (others => '0'); + + case state_reg is + --when ST_WRITE_ZEROS => -- Clear BRAM state one time case + -- wren_next <= '1'; + -- wrenb_next <= '1'; + -- addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + -- if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + -- wren_next <= '0'; + -- wrenb_next <= '0'; + -- addr_next <= (others => '0'); + -- state_next <= ST_IDLE; + -- end if; + + when ST_IDLE => -- Start + addr_next <= (others => '0'); + data_next <= (others => '0'); + averages_next <= (others => '0'); + wren_next <= '0'; + wrenb_next <= '0'; + tready_next <= '0'; + done_next <= '0'; + dinb_next <= (others => '0'); + if start = '1' then + state_next <= ST_WRITE_ZEROS; + --state_next <= ST_WAIT_TRIG; + else + state_next <= ST_IDLE; + end if; + + when ST_WRITE_ZEROS => -- Clear BRAM state + wren_next <= '1'; + wrenb_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if(unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + wren_next <= '0'; + wrenb_next <= '0'; + addr_next <= (others => '0'); + state_next <= ST_WAIT_TRIG; + end if; + + when ST_WAIT_TRIG => -- Wait for trigger + --wrenb_next <= '0'; + if(trig_i = '1') and (s_axis_tvalid = '1') then + tready_next <= '1'; + if (mode = '0') then + state_next <= ST_AVG_SCOPE; + else + state_next <= ST_AVG_N1; + end if; + else + state_next <= ST_WAIT_TRIG; + end if; + + when ST_AVG_SCOPE => -- Measure + --ASSIGN_G: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_G: for I in 0 to RATIO-1 loop + data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= + std_logic_vector(signed(dout_b_s(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + + signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH))); + end loop; + wren_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + averages_next <= std_logic_vector(unsigned(averages_reg) + 1); + addr_next <= (others => '0'); + tready_next <= '0'; + wren_next <= '0'; + if (unsigned(averages_reg) = unsigned(naverages)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WAIT_TRIG; + end if; + end if; + + when ST_AVG_N1 => -- N to 1 average + --ASSIGN_N: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_N: for I in 0 to RATIO-1 loop + data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= + std_logic_vector(signed(data_reg(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + + signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH))); + end loop; + wren_next <= '1'; + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then + if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then + averages_next <= std_logic_vector(unsigned(averages_reg) + 1); + addr_next <= (others => '0'); + tready_next <= '0'; + wren_next <= '0'; + --ASSIGN_AVG: for K in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop + ASSIGN_AVG: for K in 0 to RATIO-1 loop + dinbv := + std_logic_vector(signed(dinbv) + signed(data_reg(IN_DATA_WIDTH-1-K*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(K+1)*ADC_DATA_WIDTH))); + end loop; + dinb_next <= dinbv; + wrenb_next <= '1'; + if (unsigned(averages_reg) = unsigned(naverages)-1) then + state_next <= ST_FINISH; + else + state_next <= ST_WRITE_AVG; + end if; + end if; + + when ST_WRITE_AVG => -- write bramb + wrenb_next <= '0'; + data_next <= (others => '0'); + state_next <= ST_WAIT_TRIG; + + when ST_FINISH => -- done + wrenb_next <= '0'; + done_next <= '1'; + if restart = '1' then + --wren_next <= '1'; + --data_next <= (others => '0'); + state_next <= ST_IDLE; + end if; + end case; + end process; + +end rtl; diff --git a/cores/axis_avgr_v1_0/axis_averager.vhd b/cores/axis_avgr_v1_0/axis_averager.vhd new file mode 100644 index 0000000..9fa7018 --- /dev/null +++ b/cores/axis_avgr_v1_0/axis_averager.vhd @@ -0,0 +1,227 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_averager is + generic ( + S_AXIS_TDATA_WIDTH: natural := 128; -- AXIS itf data width + M_AXIS_TDATA_WIDTH: natural := 32; -- AXI itf data width + ADC_DATA_WIDTH : natural := 16; -- ADC data width + MEM_DEPTH : natural := 1024 --Max 2**16 + ); + port ( + start : in std_logic; + --restart : in std_logic; + trig_i : in std_logic; + send_data : in std_logic; + done : out std_logic; + + -- Slave config side + s_axis_cfg_aclk : in std_logic; + s_axis_cfg_aresetn: in std_logic; + s_axis_cfg_tready : out std_logic; + s_axis_cfg_tvalid : in std_logic; + s_axis_cfg_tdata : in std_logic_vector(64-1 downto 0); + + -- Slave data interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(S_AXIS_TDATA_WIDTH-1 downto 0); + + -- Master data interface + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + m_axis_tdata : out std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0) + ); +end axis_averager; + +architecture rtl of axis_averager is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH); + + signal nsamples_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + signal naverages_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + signal averages_out_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + signal done_s : std_logic; + signal done_sync : std_logic; + signal send_sync : std_logic; + signal start_sync : std_logic; +-- signal restart_sync : std_logic; + signal restart_s : std_logic; + signal trig_en_s : std_logic; + signal mode_s : std_logic; + + signal bram_porta_clk_s : std_logic; +-- signal bram_porta_rst_s : std_logic; + signal bram_porta_wrdata_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + signal bram_porta_we_s : std_logic; + --signal bram_porta_addr_s : std_logic_vector(AW-1 downto 0); + signal bram_porta_addr_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); --AXI itf + --signal bram_porta_rddata_s : std_logic_vector(DW-1 downto 0); + signal bram_porta_rddata_s : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); --AXI itf + + --Register cfg/sts + signal cfg_gral_reg : std_logic_vector(64-1 downto 0); + signal cfg_gral_reg_sync : std_logic_vector(64-1 downto 0); +-- signal sts_avg_reg : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); +-- signal sts_avg_reg_sync : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + signal rd_cfg_word : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); + +begin + + --done <= done_s; + + --lets synchronize the start signal + sync_start: entity work.sync + port map( + clk => s_axis_aclk, + reset => s_axis_aresetn, + in_async => start, + out_sync => start_sync + ); + + --lets synchronize the restart signal +-- sync_restart: entity work.sync +-- port map( +-- clk => s_axis_aclk, +-- reset => s_axis_aresetn, +-- in_async => restart, +-- out_sync => restart_sync +-- ); + + --lets synchronize the done signal + sync_done: entity work.sync + port map( + clk => s_axis_cfg_aclk, + reset => s_axis_cfg_aresetn, + in_async => done_s, + out_sync => done + ); + + -- synchronizer 1 + sync_fifo: entity work.axis_fifo + generic map( + AXIS_TDATA_WIDTH => 64, + FIFO_DEPTH => 4 + ) + port map( + s_axis_aclk => s_axis_cfg_aclk, + s_axis_aresetn => s_axis_cfg_aresetn, + s_axis_tready => s_axis_cfg_tready, + s_axis_tvalid => s_axis_cfg_tvalid, + s_axis_tdata => s_axis_cfg_tdata, + + m_axis_aclk => s_axis_aclk, + m_axis_aresetn => s_axis_aresetn, + m_axis_tready => '1', + m_axis_tvalid => open, + m_axis_tdata => cfg_gral_reg_sync + ); + + mode_s <= cfg_gral_reg_sync(64-1); + naverages_s <= '0' & cfg_gral_reg_sync(64-2 downto (64/2)); + nsamples_s <= cfg_gral_reg_sync((64/2)-1 downto 0); + + --Averager itf + avg_i : entity work.averager + generic map( + IN_DATA_WIDTH => S_AXIS_TDATA_WIDTH, + OUT_DATA_WIDTH => M_AXIS_TDATA_WIDTH, + ADC_DATA_WIDTH => ADC_DATA_WIDTH, + MEM_DEPTH => MEM_DEPTH + ) + port map( + aclk => s_axis_aclk, + aresetn => s_axis_aresetn, + start => start_sync, + restart => restart_s, + mode => mode_s, --0- (default) avg scope, 1-avg nsamples to one value + trig_i => trig_i, + nsamples => nsamples_s, + naverages => naverages_s, + done => done_s, + averages_out => averages_out_s, + + bram_porta_clk => bram_porta_clk_s, + --bram_porta_rst => bram_porta_rst_s, + bram_porta_wrdata => (others => '0'), + bram_porta_we => '0', + bram_porta_addr => bram_porta_addr_s, + bram_porta_rddata => bram_porta_rddata_s, + + s_axis_tready => s_axis_tready, + s_axis_tvalid => s_axis_tvalid, + s_axis_tdata => s_axis_tdata + ); + + -- determine how many data we need to read from m_axis + -- it depends of the working MODE + -- MODE=0 (averaging scope mode) -> so we need to read NSAMPLES samples + -- MODE=1 (nsamples mode) -> so we need to read NAVERAGES samples + rd_cfg_word <= nsamples_s when (mode_s = '0') else + naverages_s; + + --lets synchronize the done signal + sync_mdone: entity work.sync + port map( + clk => m_axis_aclk, + reset => m_axis_aresetn, + in_async => done_s, + out_sync => done_sync + ); + + --lets synchronize the send_data signal + sync_send: entity work.sync + port map( + clk => m_axis_aclk, + reset => m_axis_aresetn, + in_async => send_data, + out_sync => send_sync + ); + + --AXIS interface bram reader avg scope and nsamples modes + axis_bram_itf: entity work.axis_bram_reader + generic map( + BRAM_DEPTH => MEM_DEPTH, + BRAM_DATA_WIDTH => M_AXIS_TDATA_WIDTH, + AXIS_TDATA_WIDTH => M_AXIS_TDATA_WIDTH + ) + port map( + aclk => m_axis_aclk, + aresetn => m_axis_aresetn, + + cfg_data => rd_cfg_word, + sts_data => open, + done => done_sync, + send => send_sync, + restart_o => restart_s, + + m_axis_tready => m_axis_tready, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tlast => m_axis_tlast, + + bram_porta_clk => bram_porta_clk_s, + -- bram_porta_rst => bram_porta_rst_s, + bram_porta_addr => bram_porta_addr_s, + bram_porta_rddata => bram_porta_rddata_s + ); + +end rtl; diff --git a/cores/axis_avgr_v1_0/axis_bram_reader.vhd b/cores/axis_avgr_v1_0/axis_bram_reader.vhd new file mode 100644 index 0000000..dc528ca --- /dev/null +++ b/cores/axis_avgr_v1_0/axis_bram_reader.vhd @@ -0,0 +1,147 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_bram_reader is + generic ( + BRAM_DEPTH : natural := 1024; + BRAM_DATA_WIDTH : natural := 32; + AXIS_TDATA_WIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + sts_data : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + done : in std_logic; + send : in std_logic; + restart_o : out std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic; + + -- BRAM port + bram_porta_clk : out std_logic; + --bram_porta_rst : out std_logic; + bram_porta_addr : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + bram_porta_rddata: in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) + ); +end axis_bram_reader; + +architecture rtl of axis_bram_reader is + + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant BRAM_ADDR_WIDTH : integer := log2c(BRAM_DEPTH); + + type state_t is ( + ST_IDLE, + ST_DLY1, + --ST_WAIT_READY, + ST_SEND_DATA +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : unsigned(BRAM_ADDR_WIDTH-1 downto 0); +signal tvalid_s, tlast_s : std_logic; +signal tvalid_reg, tvalid_next : std_logic; +signal tlast_reg, tlast_next : std_logic; + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + state_reg <= ST_IDLE; + addr_reg <= (others => '1'); + tvalid_reg <= '0'; + tlast_reg <= '0'; + else + state_reg <= state_next; + addr_reg <= addr_next; + tvalid_reg <= tvalid_next; + tlast_reg <= tlast_next; + end if; + end if; + end process; + + --Next state logic + process(state_reg, addr_reg, done, send, m_axis_tready) + begin + state_next <= state_reg; + addr_next <= addr_reg; + --tvalid_s <= '0'; + tvalid_next <= '0'; + tlast_next <= '0'; + --tlast_s <= '0'; + + case state_reg is + when ST_IDLE => + if (done = '1') and (send = '1') then + addr_next <= addr_reg + 1; + state_next <= ST_DLY1; + else + state_next <= ST_IDLE; + end if; + + when ST_DLY1 => + addr_next <= addr_reg + 1; + state_next <= ST_SEND_DATA; + --state_next <= ST_WAIT_READY; + + --when ST_WAIT_READY => + -- if m_axis_tready = '1' then + -- state_next <= ST_SEND_DATA; + -- addr_next <= addr_reg + 1; + -- end if; + + when ST_SEND_DATA => + --tvalid_s <= '1'; + tvalid_next <= '1'; + if m_axis_tready = '1' then + addr_next <= addr_reg + 1; + if (addr_reg = unsigned(cfg_data)) then + addr_next <= (others => '1'); + state_next <= ST_IDLE; + --tlast_s <= '1'; + tlast_next <= '1'; + else + state_next <= ST_SEND_DATA; + end if; + else + state_next <= ST_SEND_DATA; + end if; + end case; + end process; + + sts_data <= std_logic_vector(resize(addr_reg,sts_data'length)); + + m_axis_tdata <= bram_porta_rddata; + --m_axis_tvalid <= tvalid_s; + m_axis_tvalid <= tvalid_reg; + --m_axis_tlast <= tlast_s; + m_axis_tlast <= tlast_reg; + + bram_porta_clk <= aclk; + --bram_porta_rst <= aresetn; + bram_porta_addr <= std_logic_vector(resize(addr_next,bram_porta_addr'length)); + restart_o <= tlast_reg; + +end rtl; diff --git a/cores/axis_avgr_v1_0/axis_fifo.vhd b/cores/axis_avgr_v1_0/axis_fifo.vhd new file mode 100644 index 0000000..67d8ab6 --- /dev/null +++ b/cores/axis_avgr_v1_0/axis_fifo.vhd @@ -0,0 +1,124 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_fifo is + generic( + AXIS_TDATA_WIDTH : natural := 32; + FIFO_DEPTH : natural := 16 + -- AWIDTH : natural := 2 + ); + port( + -- Slave data interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Master data interface + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic; + --m_axis_tlast : out std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) + ); +end axis_fifo; + +architecture rtl of axis_fifo is + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant AWIDTH : natural := log2c(FIFO_DEPTH); + + signal s_tready_reg, s_tready_next : std_logic; + signal m_tvalid_reg, m_tvalid_next : std_logic; + signal we_s, rd_s, full_s, empty_s : std_logic; + signal w_addr_s, r_addr_s : std_logic_vector(AWIDTH-1 downto 0); + +begin + + s_axis_tready <= s_tready_reg; + + --slave port registers + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + s_tready_reg <= '0'; + else + s_tready_reg <= s_tready_next; + end if; + end if; + end process; + --next state logic + s_tready_next <= '1' when (full_s = '0') else '0'; + we_s <= '1' when (full_s = '0') and (s_axis_tvalid = '1') else '0'; + + m_axis_tvalid <= m_tvalid_reg; + --master port registers + process(m_axis_aclk) + begin + if rising_edge(m_axis_aclk) then + if (m_axis_aresetn = '0') then + m_tvalid_reg <= '0'; + else + m_tvalid_reg <= m_tvalid_next; + end if; + end if; + end process; + --next state logic + m_tvalid_next <= '1' when (empty_s = '0') else '0'; + rd_s <= '1' when (empty_s = '0') and (m_axis_tready = '1') else '0'; + + --port a is wr port (slave) + --port b is rd port (master) + dp_ram_i: entity work.tdp_bram + generic map( + AWIDTH => AWIDTH, + DWIDTH => AXIS_TDATA_WIDTH + ) + port map( + clka => s_axis_aclk, + clkb => m_axis_aclk, + ena => '1', + enb => '1', + wea => we_s, + web => '0', + addra => w_addr_s, + addrb => r_addr_s, + dia => s_axis_tdata, + dib => (others => '0'), + doa => open, + dob => m_axis_tdata + ); + + fifo_ctrl_i: entity work.fifo_async_ctrl + generic map( + --DEPTH => FIFO_DEPTH + DEPTH => AWIDTH + ) + port map( + clkw => s_axis_aclk, + resetw => s_axis_aresetn, + wr => we_s, + full => full_s, + w_addr => w_addr_s, + clkr => m_axis_aclk, + resetr => m_axis_aresetn, + rd => rd_s, + empty => empty_s, + r_addr => r_addr_s + ); + +end rtl; diff --git a/cores/axis_avgr_v1_0/core_config.tcl b/cores/axis_avgr_v1_0/core_config.tcl new file mode 100644 index 0000000..0099878 --- /dev/null +++ b/cores/axis_avgr_v1_0/core_config.tcl @@ -0,0 +1,36 @@ +set display_name {AXI4-Stream Averager v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter S_AXIS_TDATA_WIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter M_AXIS_TDATA_WIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.} +core_parameter ADC_DATA_WIDTH {ADC DATA WIDTH} {Width of the ADC data.} +core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis_cfg] +set_property NAME S_AXIS_CFG $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axis_cfg_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS_CFG $parameter + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces m_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter + diff --git a/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd b/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd new file mode 100644 index 0000000..3f10117 --- /dev/null +++ b/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd @@ -0,0 +1,81 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_async_ctrl is + generic( + DEPTH: natural := 4 + ); + port( + clkw : in std_logic; + resetw : in std_logic; + wr : in std_logic; + full : out std_logic; + w_addr : out std_logic_vector (DEPTH-1 downto 0); + clkr : in std_logic; + resetr : in std_logic; + rd : in std_logic; + empty : out std_logic; + r_addr : out std_logic_vector (DEPTH-1 downto 0) + ); +end fifo_async_ctrl ; + +architecture str_arch of fifo_async_ctrl is + + signal r_ptr_in : std_logic_vector(DEPTH downto 0); + signal r_ptr_out : std_logic_vector(DEPTH downto 0); + signal w_ptr_in : std_logic_vector(DEPTH downto 0); + signal w_ptr_out : std_logic_vector(DEPTH downto 0); + +begin + read_ctrl: entity work.fifo_read_ctrl + generic map( + N=>DEPTH + ) + port map ( + clkr => clkr, + resetr => resetr, + rd => rd, + w_ptr_in => w_ptr_in, + empty => empty, + r_ptr_out=> r_ptr_out, + r_addr => r_addr + ); + + write_ctrl: entity work.fifo_write_ctrl + generic map( + N =>DEPTH + ) + port map( + clkw => clkw, + resetw => resetw, + wr => wr, + r_ptr_in => r_ptr_in, + full => full, + w_ptr_out => w_ptr_out, + w_addr => w_addr + ); + + sync_w_ptr: entity work.n_sync + generic map( + N=>DEPTH+1 + ) + port map( + clk => clkw, + reset => resetw, + in_async => w_ptr_out, + out_sync => w_ptr_in + ); + + sync_r_ptr: entity work.n_sync + generic map( + N=>DEPTH+1 + ) + port map( + clk => clkr, + reset => resetr, + in_async => r_ptr_out, + out_sync => r_ptr_in + ); + +end str_arch; diff --git a/cores/axis_avgr_v1_0/fifo_read.vhd b/cores/axis_avgr_v1_0/fifo_read.vhd new file mode 100644 index 0000000..65d0f7c --- /dev/null +++ b/cores/axis_avgr_v1_0/fifo_read.vhd @@ -0,0 +1,62 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_read_ctrl is + generic( + N: natural :=4 + ); + port( + clkr : in std_logic; + resetr : in std_logic; + w_ptr_in : in std_logic_vector(N downto 0); + rd : in std_logic; + empty : out std_logic; + r_ptr_out: out std_logic_vector(N downto 0); + r_addr : out std_logic_vector(N-1 downto 0) + ); +end fifo_read_ctrl; + +architecture gray_arch of fifo_read_ctrl is + signal r_ptr_reg, r_ptr_next : std_logic_vector(N downto 0); + signal gray1, bin, bin1 : std_logic_vector(N downto 0); + signal raddr_all : std_logic_vector(N-1 downto 0); + signal raddr_msb,waddr_msb : std_logic; + signal empty_flag : std_logic; + +begin + + -- register + process(clkr) + begin + if rising_edge(clkr) then + if (resetr='0') then + r_ptr_reg <= (others=>'0'); + else + r_ptr_reg <= r_ptr_next; + end if; + end if; + end process; + + -- (N+1)-bit Gray counter + bin <= r_ptr_reg xor ('0' & bin(N downto 1)); + bin1 <= std_logic_vector(unsigned(bin) + 1); + gray1 <= bin1 xor ('0' & bin1(N downto 1)); + + -- update read pointer + r_ptr_next <= gray1 when rd='1' and empty_flag='0' else + r_ptr_reg; + -- N-bit Gray counter + raddr_msb <= r_ptr_reg(N) xor r_ptr_reg(N-1); + raddr_all <= raddr_msb & r_ptr_reg(N-2 downto 0); + waddr_msb <= w_ptr_in(N) xor w_ptr_in(N-1); + -- check for FIFO empty + empty_flag <= '1' when w_ptr_in(N)=r_ptr_reg(N) and + w_ptr_in(N-2 downto 0)=r_ptr_reg(N-2 downto 0) and + raddr_msb = waddr_msb else + '0'; + -- output + r_addr <= raddr_all; + r_ptr_out <= r_ptr_reg; + empty <= empty_flag; +end gray_arch; diff --git a/cores/axis_avgr_v1_0/fifo_write.vhd b/cores/axis_avgr_v1_0/fifo_write.vhd new file mode 100644 index 0000000..46d8310 --- /dev/null +++ b/cores/axis_avgr_v1_0/fifo_write.vhd @@ -0,0 +1,62 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_write_ctrl is + generic( + N : natural := 4 + ); + port( + clkw : in std_logic; + resetw : in std_logic; + wr : in std_logic; + r_ptr_in : in std_logic_vector(N downto 0); + full : out std_logic; + w_ptr_out: out std_logic_vector(N downto 0); + w_addr : out std_logic_vector(N-1 downto 0) + ); +end fifo_write_ctrl; + +architecture gray_arch of fifo_write_ctrl is + signal w_ptr_reg, w_ptr_next :std_logic_vector(N downto 0); + signal gray1, bin, bin1 : std_logic_vector(N downto 0); + signal waddr_all : std_logic_vector(N-1 downto 0); + signal waddr_msb, raddr_msb : std_logic; + signal full_flag : std_logic; + +begin + + -- register + process(clkw) + begin + if rising_edge(clkw) then + if (resetw='0') then + w_ptr_reg <= (others=>'0'); + else + w_ptr_reg <= w_ptr_next; + end if; + end if; + end process; + + -- (N+1)-bit Gray counter + bin <= w_ptr_reg xor ('0' & bin(N downto 1)); + bin1 <= std_logic_vector(unsigned(bin) + 1); + gray1 <= bin1 xor ('0' & bin1(N downto 1)); + -- update write pointer + w_ptr_next <= gray1 when wr='1' and full_flag='0' else + w_ptr_reg; + -- N-bit Gray counter + waddr_msb <= w_ptr_reg(N) xor w_ptr_reg(N-1); + waddr_all <= waddr_msb & w_ptr_reg(N-2 downto 0); + -- check for FIFO full + raddr_msb <= r_ptr_in(N) xor r_ptr_in(N-1); + full_flag <= '1' when r_ptr_in(N) /=w_ptr_reg(N) and + r_ptr_in(N-2 downto 0)=w_ptr_reg(N-2 downto 0) and + raddr_msb = waddr_msb else + '0'; + -- output + w_addr <= waddr_all; + w_ptr_out <= w_ptr_reg; + full <= full_flag; + +end gray_arch; diff --git a/cores/axis_avgr_v1_0/n_sync.vhd b/cores/axis_avgr_v1_0/n_sync.vhd new file mode 100644 index 0000000..3969669 --- /dev/null +++ b/cores/axis_avgr_v1_0/n_sync.vhd @@ -0,0 +1,41 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity n_sync is + generic( + N : natural + ); + port( + clk : in std_logic; + reset : in std_logic; + in_async : in std_logic_vector(N-1 downto 0); + out_sync : out std_logic_vector(N-1 downto 0) + ); +end n_sync; + +architecture two_ff_arch of n_sync is + signal meta_reg, sync_reg : std_logic_vector(N-1 downto 0); + signal meta_next, sync_next: std_logic_vector(N-1 downto 0); +begin + + -- two registers + process(clk) + begin + if rising_edge(clk) then + if (reset='0') then + meta_reg <= (others=>'0'); + sync_reg <= (others=>'0'); + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr_v1_0/sync.vhd b/cores/axis_avgr_v1_0/sync.vhd new file mode 100644 index 0000000..ca83fec --- /dev/null +++ b/cores/axis_avgr_v1_0/sync.vhd @@ -0,0 +1,39 @@ +library ieee; +use ieee.std_logic_1164.all; + +--synchronizer +entity sync is + port( + clk : in std_logic; + reset : in std_logic; + in_async : in std_logic; + out_sync : out std_logic + ); +end sync; + +architecture two_ff_arch of sync is + signal meta_reg, sync_reg : std_logic; + signal meta_next, sync_next: std_logic; +begin + + -- two registers + process(clk) + begin + if rising_edge(clk) then + if (reset='0') then + meta_reg <= '0'; + sync_reg <= '0'; + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_avgr_v1_0/tdp_bram.vhd b/cores/axis_avgr_v1_0/tdp_bram.vhd new file mode 100644 index 0000000..e991a17 --- /dev/null +++ b/cores/axis_avgr_v1_0/tdp_bram.vhd @@ -0,0 +1,60 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity tdp_bram is + generic ( + AWIDTH : integer := 16; + DWIDTH : integer := 16 + ); + port ( + clka : in std_logic; + clkb : in std_logic; + ena : in std_logic; + enb : in std_logic; + wea : in std_logic; + web : in std_logic; + addra : in std_logic_vector (AWIDTH-1 downto 0); + addrb : in std_logic_vector (AWIDTH-1 downto 0); + dia : in std_logic_vector (DWIDTH-1 downto 0); + dib : in std_logic_vector (DWIDTH-1 downto 0); + doa : out std_logic_vector (DWIDTH-1 downto 0); + dob : out std_logic_vector (DWIDTH-1 downto 0) + ); +end tdp_bram; + +architecture rtl of tdp_bram is + + type ram_t is array (2**AWIDTH-1 downto 0) of std_logic_vector (DWIDTH-1 downto 0); + shared variable ram : ram_t; + +begin + + -- clka port. + process (clka) + begin + if rising_edge(clka) then + if (ena = '1') then + doa <= ram(to_integer(unsigned(addra))); + if (wea = '1') then + ram(to_integer(unsigned(addra))) := dia; + end if; + end if; + end if; + end process; + + -- clkb port. + process (clkb) + begin + if rising_edge(clkb) then + if (enb = '1') then + dob <= ram(to_integer(unsigned(addrb))); + if (web = '1') then + ram(to_integer(unsigned(addrb))) := dib; + end if; + end if; + end if; + end process; + +end rtl; + diff --git a/cores/axis_counter_v1_0/axis_counter.vhd b/cores/axis_counter_v1_0/axis_counter.vhd new file mode 100644 index 0000000..6017cdb --- /dev/null +++ b/cores/axis_counter_v1_0/axis_counter.vhd @@ -0,0 +1,61 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_counter is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + CNTR_WIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data : in std_logic_vector(CNTR_WIDTH-1 downto 0); + + -- Master side + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tlast : out std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic + ); +end axis_counter; + +architecture rtl of axis_counter is + + signal cntr_reg, cntr_next : unsigned(CNTR_WIDTH-1 downto 0); + signal tlast_reg, tlast_next : std_logic; + signal comp_reg, comp_next : std_logic; + +begin + + process(aclk) + begin + if (rising_edge(aclk)) then + if(aresetn = '0') then + cntr_reg <= (others => '0'); + tlast_reg <= '0'; + comp_reg <= '0'; + else + cntr_reg <= cntr_next; + tlast_reg <= tlast_next; + comp_reg <= comp_next; + end if; + end if; + end process; + + tlast_next <= '1' when (cntr_reg = unsigned(cfg_data)-2) else '0'; + + comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else '1'; + + cntr_next <= cntr_reg + 1 when ((comp_reg = '1') and (m_axis_tready = '1')) else + (others => '0') when (comp_reg = '0') else --reset + cntr_reg; + + m_axis_tdata <= std_logic_vector(resize(cntr_reg, m_axis_tdata'length)); + m_axis_tlast <= tlast_reg; + m_axis_tvalid <= comp_reg; + +end rtl; diff --git a/cores/axis_counter_v1_0/core_config.tcl b/cores/axis_counter_v1_0/core_config.tcl new file mode 100644 index 0000000..c86878a --- /dev/null +++ b/cores/axis_counter_v1_0/core_config.tcl @@ -0,0 +1,17 @@ +set display_name {AXI4-Stream Counter} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.} +core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter diff --git a/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd b/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd new file mode 100644 index 0000000..3b42e8b --- /dev/null +++ b/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd @@ -0,0 +1,94 @@ +-- See WP279 from Xilinx +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_dc_removal is + generic( + AXIS_TDATA_WIDTH : integer := 32 + ); + port ( + aclk : in std_logic; + aresetn : in std_logic; + k1_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + k2_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic + + ); +end axis_dc_removal; + +architecture rtl of axis_dc_removal is + + signal d1_reg, d1_next : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal d2_reg, d2_next : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal d3_reg, d3_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal ch1_s, ch2_s : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal axis_tready : std_logic; + signal axis_tvalid : std_logic; + +begin + + axis_tready <= '1'; + s_axis_tready <= axis_tready; + m_axis_tvalid <= axis_tvalid; + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + d1_reg <= (others => '0'); + d2_reg <= (others => '0'); + d3_reg <= (others => '0'); + else + d1_reg <= d1_next; + d2_reg <= d2_next; + d3_reg <= d3_next; + end if; + end if; + end process; + + d1_next <= s_axis_tdata(AXIS_TDATA_WIDTH/2-1 downto 0) when + ((axis_tready = '1') and (s_axis_tvalid = '1')) else + d1_reg; + d2_next <= s_axis_tdata(AXIS_TDATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2) + when ((axis_tready = '1') and (s_axis_tvalid = '1')) else + d2_reg; + + d3_next <= ch2_s & ch1_s when ((m_axis_tready = '1') and (axis_tvalid = '1')) else + d3_reg; + + + --dc removal for ch1 + ch1_dcrm: entity work.dc_removal + port map( + aclk => aclk, + aresetn => aresetn, + k_i => k1_i, + data_i => d1_reg, + data_o => ch1_s + ); + + --dc removal for ch2 + ch2_dcrm: entity work.dc_removal + port map( + aclk => aclk, + aresetn => aresetn, + k_i => k2_i, + data_i => d2_reg, + data_o => ch2_s + ); + + axis_tvalid <= '1'; + m_axis_tdata <= d3_reg; + +end rtl; diff --git a/cores/axis_dc_removal_v1_0/core_config.tcl b/cores/axis_dc_removal_v1_0/core_config.tcl new file mode 100644 index 0000000..2588708 --- /dev/null +++ b/cores/axis_dc_removal_v1_0/core_config.tcl @@ -0,0 +1,21 @@ +set display_name {AXI4-Stream Digital DC Removal Circuit} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter + diff --git a/cores/axis_dc_removal_v1_0/dc_removal.vhd b/cores/axis_dc_removal_v1_0/dc_removal.vhd new file mode 100644 index 0000000..75c732b --- /dev/null +++ b/cores/axis_dc_removal_v1_0/dc_removal.vhd @@ -0,0 +1,92 @@ +-- See WP279 from Xilinx +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity dc_removal is + generic( + DATA_WIDTH : integer := 16 + ); + port ( + aclk : in std_logic; + aresetn : in std_logic; + k_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + data_i : in std_logic_vector(DATA_WIDTH-1 downto 0); + data_o : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end dc_removal; + +architecture rtl of dc_removal is + signal k_reg, k_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d0_reg, d0_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d11_reg, d11_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d12_reg, d12_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d21_reg, d21_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d22_reg, d22_next : std_logic_vector(2*DATA_WIDTH-1 downto 0); + signal d31_reg, d31_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal d32_reg, d32_next : std_logic_vector(2*DATA_WIDTH-1 downto 0); + signal d4_reg, d4_next : std_logic_vector(DATA_WIDTH-1 downto 0); + signal mult_s : std_logic_vector(2*DATA_WIDTH-1 downto 0); + signal sub_s : std_logic_vector(DATA_WIDTH-1 downto 0); + signal sub2_s : std_logic_vector(DATA_WIDTH-1 downto 0); + signal data_fbk : std_logic_vector(DATA_WIDTH-1 downto 0); + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + k_reg <= (others => '0'); + d0_reg <= (others => '0'); + d11_reg <= (others => '0'); + d12_reg <= (others => '0'); + d21_reg <= (others => '0'); + d22_reg <= (others => '0'); + d31_reg <= (others => '0'); + d32_reg <= (others => '0'); + d4_reg <= (others => '0'); + else + k_reg <= k_next; + d0_reg <= d0_next; + d11_reg <= d11_next; + d12_reg <= d12_next; + d21_reg <= d21_next; + d22_reg <= d22_next; + d31_reg <= d31_next; + d32_reg <= d32_next; + d4_reg <= d4_next; + end if; + end if; + end process; + + k_next <= k_i; + + d0_next <= data_i; + + d11_next <= d0_reg; + + sub_s <= std_logic_vector(signed(d0_reg) - signed(data_fbk)); + + d12_next <= sub_s; + + d21_next <= d11_reg; + + mult_s <= std_logic_vector(signed(k_reg) * signed(d12_reg)); + + d22_next <= mult_s; + + d31_next <= d21_reg; + + d32_next <= std_logic_vector(signed(d32_reg) + signed(d22_reg)); + + data_fbk <= d32_reg(2*DATA_WIDTH-1 downto DATA_WIDTH); + + sub2_s <= std_logic_vector(signed(d31_reg) - signed(data_fbk)); + + d4_next <= sub2_s; + + data_o <= d4_reg; + +end rtl; diff --git a/cores/axis_fifo_v1_0/axis_fifo.vhd b/cores/axis_fifo_v1_0/axis_fifo.vhd new file mode 100644 index 0000000..862f7a0 --- /dev/null +++ b/cores/axis_fifo_v1_0/axis_fifo.vhd @@ -0,0 +1,124 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_fifo is + generic( + AXIS_TDATA_WIDTH : natural := 32; + FIFO_DEPTH : natural := 16 + -- AWIDTH : natural := 2 + ); + port( + -- Slave data interface + s_axis_aclk : in std_logic; + s_axis_aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Master data interface + m_axis_aclk : in std_logic; + m_axis_aresetn : in std_logic; + m_axis_tready : in std_logic; + m_axis_tvalid : out std_logic; + --m_axis_tlast : out std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) + ); +end axis_fifo; + +architecture rtl of axis_fifo is + function log2c(n: integer) return integer is + variable m, p: integer; + begin + m := 0; + p := 1; + while p < n loop + m := m + 1; + p := p * 2; + end loop; + return m; + end log2c; + + constant AWIDTH : natural := log2c(FIFO_DEPTH); + + signal s_tready_reg, s_tready_next : std_logic; + signal m_tvalid_reg, m_tvalid_next : std_logic; + signal we_s, rd_s, full_s, empty_s : std_logic; + signal w_addr_s, r_addr_s : std_logic_vector(AWIDTH-1 downto 0); + +begin + + s_axis_tready <= s_tready_reg; + + --slave port registers + process(s_axis_aclk) + begin + if rising_edge(s_axis_aclk) then + if (s_axis_aresetn = '0') then + s_tready_reg <= '0'; + else + s_tready_reg <= s_tready_next; + end if; + end if; + end process; + --next state logic + s_tready_next <= '1' when (full_s = '0') else '0'; + we_s <= '1' when (full_s = '0') and (s_axis_tvalid = '1') else '0'; + + m_axis_tvalid <= m_tvalid_reg; + --master port registers + process(m_axis_aclk) + begin + if rising_edge(m_axis_aclk) then + if (m_axis_aresetn = '0') then + m_tvalid_reg <= '0'; + else + m_tvalid_reg <= m_tvalid_next; + end if; + end if; + end process; + --next state logic + m_tvalid_next <= '1' when (empty_s = '0') else '0'; + rd_s <= '1' when (empty_s = '0') and (m_axis_tready = '1') else '0'; + + --port a is wr port (slave) + --port b is rd port (master) + dp_ram_i: entity work.dp_ram + generic map( + AWIDTH => AWIDTH, + DWIDTH => AXIS_TDATA_WIDTH + ) + port map( + clka => s_axis_aclk, + clkb => m_axis_aclk, + ena => '1', + enb => '1', + wea => we_s, + web => '0', + addra => w_addr_s, + addrb => r_addr_s, + dia => s_axis_tdata, + dib => (others => '0'), + doa => open, + dob => m_axis_tdata + ); + + fifo_ctrl_i: entity work.fifo_async_ctrl + generic map( + --DEPTH => FIFO_DEPTH + DEPTH => AWIDTH + ) + port map( + clkw => s_axis_aclk, + resetw => s_axis_aresetn, + wr => we_s, + full => full_s, + w_addr => w_addr_s, + clkr => m_axis_aclk, + resetr => m_axis_aresetn, + rd => rd_s, + empty => empty_s, + r_addr => r_addr_s + ); + +end rtl; diff --git a/cores/axis_fifo_v1_0/core_config.tcl b/cores/axis_fifo_v1_0/core_config.tcl new file mode 100644 index 0000000..416eb3b --- /dev/null +++ b/cores/axis_fifo_v1_0/core_config.tcl @@ -0,0 +1,26 @@ +set display_name {AXI4-Stream FIFO v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter FIFO_DEPTH {FIFO DEPTH} {Depth of the FIFO.} +#core_parameter AWIDTH {ADDRESS WIDTH} {Determines the depth of the FIFO.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces s_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces m_axis_aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter diff --git a/cores/axis_fifo_v1_0/dp_bram.vhd b/cores/axis_fifo_v1_0/dp_bram.vhd new file mode 100644 index 0000000..d483c49 --- /dev/null +++ b/cores/axis_fifo_v1_0/dp_bram.vhd @@ -0,0 +1,60 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity dp_ram is + generic ( + AWIDTH : integer := 16; + DWIDTH : integer := 16 + ); + port ( + clka : in std_logic; + clkb : in std_logic; + ena : in std_logic; + enb : in std_logic; + wea : in std_logic; + web : in std_logic; + addra : in std_logic_vector (AWIDTH-1 downto 0); + addrb : in std_logic_vector (AWIDTH-1 downto 0); + dia : in std_logic_vector (DWIDTH-1 downto 0); + dib : in std_logic_vector (DWIDTH-1 downto 0); + doa : out std_logic_vector (DWIDTH-1 downto 0); + dob : out std_logic_vector (DWIDTH-1 downto 0) + ); +end dp_ram; + +architecture rtl of dp_ram is + + type ram_t is array (2**AWIDTH-1 downto 0) of std_logic_vector (DWIDTH-1 downto 0); + shared variable ram : ram_t; + +begin + + -- clka port. + process (clka) + begin + if rising_edge(clka) then + if (ena = '1') then + doa <= ram(conv_integer(addra)); + if (wea = '1') then + ram(conv_integer(addra)) := dia; + end if; + end if; + end if; + end process; + + -- clkb port. + process (clkb) + begin + if rising_edge(clkb) then + if (enb = '1') then + dob <= ram(conv_integer(addrb)); + if (web = '1') then + ram(conv_integer(addrb)) := dib; + end if; + end if; + end if; + end process; + +end rtl; + diff --git a/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd b/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd new file mode 100644 index 0000000..3f10117 --- /dev/null +++ b/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd @@ -0,0 +1,81 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_async_ctrl is + generic( + DEPTH: natural := 4 + ); + port( + clkw : in std_logic; + resetw : in std_logic; + wr : in std_logic; + full : out std_logic; + w_addr : out std_logic_vector (DEPTH-1 downto 0); + clkr : in std_logic; + resetr : in std_logic; + rd : in std_logic; + empty : out std_logic; + r_addr : out std_logic_vector (DEPTH-1 downto 0) + ); +end fifo_async_ctrl ; + +architecture str_arch of fifo_async_ctrl is + + signal r_ptr_in : std_logic_vector(DEPTH downto 0); + signal r_ptr_out : std_logic_vector(DEPTH downto 0); + signal w_ptr_in : std_logic_vector(DEPTH downto 0); + signal w_ptr_out : std_logic_vector(DEPTH downto 0); + +begin + read_ctrl: entity work.fifo_read_ctrl + generic map( + N=>DEPTH + ) + port map ( + clkr => clkr, + resetr => resetr, + rd => rd, + w_ptr_in => w_ptr_in, + empty => empty, + r_ptr_out=> r_ptr_out, + r_addr => r_addr + ); + + write_ctrl: entity work.fifo_write_ctrl + generic map( + N =>DEPTH + ) + port map( + clkw => clkw, + resetw => resetw, + wr => wr, + r_ptr_in => r_ptr_in, + full => full, + w_ptr_out => w_ptr_out, + w_addr => w_addr + ); + + sync_w_ptr: entity work.n_sync + generic map( + N=>DEPTH+1 + ) + port map( + clk => clkw, + reset => resetw, + in_async => w_ptr_out, + out_sync => w_ptr_in + ); + + sync_r_ptr: entity work.n_sync + generic map( + N=>DEPTH+1 + ) + port map( + clk => clkr, + reset => resetr, + in_async => r_ptr_out, + out_sync => r_ptr_in + ); + +end str_arch; diff --git a/cores/axis_fifo_v1_0/fifo_read.vhd b/cores/axis_fifo_v1_0/fifo_read.vhd new file mode 100644 index 0000000..65d0f7c --- /dev/null +++ b/cores/axis_fifo_v1_0/fifo_read.vhd @@ -0,0 +1,62 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_read_ctrl is + generic( + N: natural :=4 + ); + port( + clkr : in std_logic; + resetr : in std_logic; + w_ptr_in : in std_logic_vector(N downto 0); + rd : in std_logic; + empty : out std_logic; + r_ptr_out: out std_logic_vector(N downto 0); + r_addr : out std_logic_vector(N-1 downto 0) + ); +end fifo_read_ctrl; + +architecture gray_arch of fifo_read_ctrl is + signal r_ptr_reg, r_ptr_next : std_logic_vector(N downto 0); + signal gray1, bin, bin1 : std_logic_vector(N downto 0); + signal raddr_all : std_logic_vector(N-1 downto 0); + signal raddr_msb,waddr_msb : std_logic; + signal empty_flag : std_logic; + +begin + + -- register + process(clkr) + begin + if rising_edge(clkr) then + if (resetr='0') then + r_ptr_reg <= (others=>'0'); + else + r_ptr_reg <= r_ptr_next; + end if; + end if; + end process; + + -- (N+1)-bit Gray counter + bin <= r_ptr_reg xor ('0' & bin(N downto 1)); + bin1 <= std_logic_vector(unsigned(bin) + 1); + gray1 <= bin1 xor ('0' & bin1(N downto 1)); + + -- update read pointer + r_ptr_next <= gray1 when rd='1' and empty_flag='0' else + r_ptr_reg; + -- N-bit Gray counter + raddr_msb <= r_ptr_reg(N) xor r_ptr_reg(N-1); + raddr_all <= raddr_msb & r_ptr_reg(N-2 downto 0); + waddr_msb <= w_ptr_in(N) xor w_ptr_in(N-1); + -- check for FIFO empty + empty_flag <= '1' when w_ptr_in(N)=r_ptr_reg(N) and + w_ptr_in(N-2 downto 0)=r_ptr_reg(N-2 downto 0) and + raddr_msb = waddr_msb else + '0'; + -- output + r_addr <= raddr_all; + r_ptr_out <= r_ptr_reg; + empty <= empty_flag; +end gray_arch; diff --git a/cores/axis_fifo_v1_0/fifo_write.vhd b/cores/axis_fifo_v1_0/fifo_write.vhd new file mode 100644 index 0000000..46d8310 --- /dev/null +++ b/cores/axis_fifo_v1_0/fifo_write.vhd @@ -0,0 +1,62 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity fifo_write_ctrl is + generic( + N : natural := 4 + ); + port( + clkw : in std_logic; + resetw : in std_logic; + wr : in std_logic; + r_ptr_in : in std_logic_vector(N downto 0); + full : out std_logic; + w_ptr_out: out std_logic_vector(N downto 0); + w_addr : out std_logic_vector(N-1 downto 0) + ); +end fifo_write_ctrl; + +architecture gray_arch of fifo_write_ctrl is + signal w_ptr_reg, w_ptr_next :std_logic_vector(N downto 0); + signal gray1, bin, bin1 : std_logic_vector(N downto 0); + signal waddr_all : std_logic_vector(N-1 downto 0); + signal waddr_msb, raddr_msb : std_logic; + signal full_flag : std_logic; + +begin + + -- register + process(clkw) + begin + if rising_edge(clkw) then + if (resetw='0') then + w_ptr_reg <= (others=>'0'); + else + w_ptr_reg <= w_ptr_next; + end if; + end if; + end process; + + -- (N+1)-bit Gray counter + bin <= w_ptr_reg xor ('0' & bin(N downto 1)); + bin1 <= std_logic_vector(unsigned(bin) + 1); + gray1 <= bin1 xor ('0' & bin1(N downto 1)); + -- update write pointer + w_ptr_next <= gray1 when wr='1' and full_flag='0' else + w_ptr_reg; + -- N-bit Gray counter + waddr_msb <= w_ptr_reg(N) xor w_ptr_reg(N-1); + waddr_all <= waddr_msb & w_ptr_reg(N-2 downto 0); + -- check for FIFO full + raddr_msb <= r_ptr_in(N) xor r_ptr_in(N-1); + full_flag <= '1' when r_ptr_in(N) /=w_ptr_reg(N) and + r_ptr_in(N-2 downto 0)=w_ptr_reg(N-2 downto 0) and + raddr_msb = waddr_msb else + '0'; + -- output + w_addr <= waddr_all; + w_ptr_out <= w_ptr_reg; + full <= full_flag; + +end gray_arch; diff --git a/cores/axis_fifo_v1_0/n_sync.vhd b/cores/axis_fifo_v1_0/n_sync.vhd new file mode 100644 index 0000000..3969669 --- /dev/null +++ b/cores/axis_fifo_v1_0/n_sync.vhd @@ -0,0 +1,41 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity n_sync is + generic( + N : natural + ); + port( + clk : in std_logic; + reset : in std_logic; + in_async : in std_logic_vector(N-1 downto 0); + out_sync : out std_logic_vector(N-1 downto 0) + ); +end n_sync; + +architecture two_ff_arch of n_sync is + signal meta_reg, sync_reg : std_logic_vector(N-1 downto 0); + signal meta_next, sync_next: std_logic_vector(N-1 downto 0); +begin + + -- two registers + process(clk) + begin + if rising_edge(clk) then + if (reset='0') then + meta_reg <= (others=>'0'); + sync_reg <= (others=>'0'); + else + meta_reg <= meta_next; + sync_reg <= sync_next; + end if; + end if; + end process; + + -- next-state logic + meta_next <= in_async; + sync_next <= meta_reg; + -- output + out_sync <= sync_reg; + +end two_ff_arch; diff --git a/cores/axis_generator_v1_0/axis_generator.vhd b/cores/axis_generator_v1_0/axis_generator.vhd new file mode 100644 index 0000000..8a20378 --- /dev/null +++ b/cores/axis_generator_v1_0/axis_generator.vhd @@ -0,0 +1,131 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axi_stream_generator is + generic( + AXIS_TDATA_WIDTH : natural := 32 + ); + port + ( + -- DO NOT EDIT BELOW THIS LINE --------------------- + -- Bus protocol ports, do not add or delete. + aclk : in std_logic; + aresetn : in std_logic; + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tlast : in std_logic; + s_axis_tvalid : in std_logic; + m_axis_tvalid : out std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tlast : out std_logic; + m_axis_tready : in std_logic + -- DO NOT EDIT ABOVE THIS LINE --------------------- + ); + +-- attribute SIGIS : string; +-- attribute SIGIS of ACLK : signal is "Clk"; + +end axi_stream_generator; + +------------------------------------------------------------------------------ +-- Architecture Section +------------------------------------------------------------------------------ + +-- In this section, we povide an example implementation of ENTITY axi_stream_generator +-- that does the following: +-- +-- 1. Read all inputs +-- 2. Add each input to the contents of register 'sum' which +-- acts as an accumulator +-- 3. After all the inputs have been read, write out the +-- content of 'sum' into the output stream NUMBER_OF_OUTPUT_WORDS times +-- +-- You will need to modify this example or implement a new architecture for +-- ENTITY axi_stream_generator to implement your coprocessor + +architecture EXAMPLE of axi_stream_generator is + + -- Total number of input data. + constant NUMBER_OF_INPUT_WORDS : natural := 8; + + -- Total number of output data + constant NUMBER_OF_OUTPUT_WORDS : natural := 8; + + type STATE_TYPE is (Idle, Read_Inputs, Write_Outputs); + + signal state : STATE_TYPE; + + -- Accumulator to hold sum of inputs read at any point in time + signal sum : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Counters to store the number inputs read & outputs written + signal nr_of_reads : natural range 0 to NUMBER_OF_INPUT_WORDS - 1; + signal nr_of_writes : natural range 0 to NUMBER_OF_OUTPUT_WORDS - 1; + + -- tlast signal + signal tlast : std_logic; + +begin + -- CAUTION: + -- The sequence in which data are read in and written out should be + -- consistent with the sequence they are written and read in the + -- driver's axi_stream_generator.c file + + -- s_axis_tready <= '1' when state = Read_Inputs else '0'; + s_axis_tready <= '0' when state = Write_Outputs else '1'; + m_axis_tvalid <= '1' when state = Write_Outputs else '0'; + + m_axis_tdata <= sum; + m_axis_tlast <= tlast; + + The_SW_accelerator : process (ACLK) is + begin -- process The_SW_accelerator + if ACLK'event and ACLK = '1' then -- Rising clock edge + if ARESETN = '0' then -- Synchronous reset (active low) + -- CAUTION: make sure your reset polarity is consistent with the + -- system reset polarity + state <= Idle; + nr_of_reads <= 0; + nr_of_writes <= 0; + sum <= (others => '0'); + tlast <= '0'; + else + case state is + when Idle => + if (s_axis_tvalid = '1') then + state <= Read_Inputs; + nr_of_reads <= NUMBER_OF_INPUT_WORDS - 1; + sum <= (others => '0'); + end if; + + when Read_Inputs => + if (s_axis_tvalid = '1') then + -- Coprocessor function (Adding) happens here + sum <= std_logic_vector(unsigned(sum) + unsigned(s_axis_tdata)); + if (s_axis_tlast = '1') then + state <= Write_Outputs; + nr_of_writes <= NUMBER_OF_OUTPUT_WORDS - 1; + else + nr_of_reads <= nr_of_reads - 1; + end if; + end if; + + when Write_Outputs => + if (m_axis_tready = '1') then + if (nr_of_writes = 0) then + state <= Idle; + tlast <= '0'; + else + -- assert tlast on last transmitted word + if (nr_of_writes = 1) then + tlast <= '1'; + end if; + nr_of_writes <= nr_of_writes - 1; + end if; + end if; + end case; + end if; + end if; + end process The_SW_accelerator; +end architecture EXAMPLE; diff --git a/cores/axis_generator_v1_0/core_config.tcl b/cores/axis_generator_v1_0/core_config.tcl new file mode 100644 index 0000000..7cf6e7e --- /dev/null +++ b/cores/axis_generator_v1_0/core_config.tcl @@ -0,0 +1,20 @@ +set display_name {AXI4-Stream Generator v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {TDATA WIDTH} {Width of the AXIS data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter diff --git a/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd b/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd new file mode 100644 index 0000000..b97555a --- /dev/null +++ b/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd @@ -0,0 +1,52 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity axis_gpio_reader_i is + generic ( + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + -- System signals + aclk : in std_logic; + + gpio_data : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Master side + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_gpio_reader_i; + +architecture rtl of axis_gpio_reader_i is + + type int_data_t is array (1 downto 0) of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal int_data_reg : int_data_t; + signal int_data_wire: std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + +begin + + GPIO_G: for j in 0 to AXIS_TDATA_WIDTH-1 generate + IBUF_int: IBUF + port map( + O => int_data_wire(j), + I => gpio_data(j) + ); + end generate; + + process(aclk) + begin + if (rising_edge(aclk)) then + int_data_reg(0) <= int_data_wire; + int_data_reg(1) <= int_data_reg(0); + end if; + end process; + + m_axis_tdata <= int_data_reg(1); + m_axis_tvalid <= '1'; + +end rtl; diff --git a/cores/axis_gpio_reader_i_v1_0/core_config.tcl b/cores/axis_gpio_reader_i_v1_0/core_config.tcl new file mode 100644 index 0000000..968c5d3 --- /dev/null +++ b/cores/axis_gpio_reader_i_v1_0/core_config.tcl @@ -0,0 +1,16 @@ +set display_name {AXI4-Stream GPIO Reader} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter diff --git a/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd b/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd new file mode 100644 index 0000000..9b57a63 --- /dev/null +++ b/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd @@ -0,0 +1,54 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity axis_gpio_reader is + generic ( + AXIS_TDATA_WIDTH: natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + + gpio_data : inout std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Master side + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic + ); +end axis_gpio_reader; + +architecture rtl of axis_gpio_reader is + + type int_data_t is array (1 downto 0) of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal int_data_reg : int_data_t; + signal int_data_wire: std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + +begin + + GPIO_G: for j in 0 to AXIS_TDATA_WIDTH-1 generate + IOBUF_int: IOBUF + port map( + O => int_data_wire(j), + IO => gpio_data(j), + I => '0', + T => '1' + ); + end generate; + + process(aclk) + begin + if (rising_edge(aclk)) then + int_data_reg(0) <= int_data_wire; + int_data_reg(1) <= int_data_reg(0); + end if; + end process; + + m_axis_tdata <= int_data_reg(1); + m_axis_tvalid <= '1'; + +end rtl; diff --git a/cores/axis_gpio_reader_v1_0/core_config.tcl b/cores/axis_gpio_reader_v1_0/core_config.tcl new file mode 100644 index 0000000..968c5d3 --- /dev/null +++ b/cores/axis_gpio_reader_v1_0/core_config.tcl @@ -0,0 +1,16 @@ +set display_name {AXI4-Stream GPIO Reader} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter diff --git a/cores/axis_histogram_v1_0/axis_histogram.vhd b/cores/axis_histogram_v1_0/axis_histogram.vhd new file mode 100644 index 0000000..ac29bcb --- /dev/null +++ b/cores/axis_histogram_v1_0/axis_histogram.vhd @@ -0,0 +1,124 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_histogram is + generic ( + AXIS_TDATA_WIDTH: natural := 16; + BRAM_DATA_WIDTH : natural := 32; + BRAM_ADDR_WIDTH : natural := 14 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- BRAM port + bram_porta_clk : out std_logic; + bram_porta_rst : out std_logic; + bram_porta_addr : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_we : out std_logic + ); +end axis_histogram; + +architecture rtl of axis_histogram is + + type state_t is ( + ST_IDLE, + ST_WRITE_ZEROS, + ST_READ_ADDR, + ST_DELAY1, + ST_INC_DATA, + ST_DELAY2 +); +signal state_reg, state_next : state_t; + +signal addr_reg, addr_next : std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); +signal data_reg, data_next : std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); +signal tready_reg, tready_next : std_logic; +signal wren_reg, wren_next : std_logic; +signal wren_s : std_logic; + +begin + + s_axis_tready <= tready_reg; + + bram_porta_clk <= aclk; + bram_porta_rst <= not aresetn; + bram_porta_addr <= addr_reg when (wren_reg = '1') else + s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata <= data_reg; + bram_porta_we <= wren_reg; + + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + addr_reg <= (others => '0'); + data_reg <= (others => '0'); + tready_reg <= '0'; + wren_reg <= '0'; + else + state_reg <= state_next; + addr_reg <= addr_next; + data_reg <= data_next; + tready_reg <= tready_next; + wren_reg <= wren_next; + end if; + end if; + end process; + + wren_s <= '1' when (bram_porta_rddata = (bram_porta_rddata'range => '1')) else + '0'; + + --Next state logic + process(state_reg, addr_reg, s_axis_tvalid) + begin + state_next <= state_reg; + addr_next <= addr_reg; + data_next <= data_reg; + tready_next <= tready_reg; + wren_next <= wren_reg; + + case state_reg is + when ST_IDLE => + addr_next <= (others => '0'); + data_next <= (others => '0'); + wren_next <= '1'; + state_next <= ST_WRITE_ZEROS; + when ST_WRITE_ZEROS => + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + if (addr_reg = (addr_reg'range => '1')) then + tready_next <= '1'; + wren_next <= '0'; + state_next <= ST_READ_ADDR; + end if; + when ST_READ_ADDR => + if (s_axis_tvalid = '1') then + addr_next <= s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0); + tready_next <= '0'; + state_next <= ST_DELAY1; + end if; + when ST_DELAY1 => + state_next <= ST_INC_DATA; + when ST_INC_DATA => + data_next <= std_logic_vector(unsigned(bram_porta_rddata) + 1); + wren_next <= not wren_s; --(and bram_porta_rddata); + state_next <= ST_DELAY2; + when ST_DELAY2 => + tready_next <= '1'; + wren_next <= '0'; + state_next <= ST_READ_ADDR; + end case; + end process; + +end rtl; diff --git a/cores/axis_histogram_v1_0/core_config.tcl b/cores/axis_histogram_v1_0/core_config.tcl new file mode 100644 index 0000000..0a3e5e6 --- /dev/null +++ b/cores/axis_histogram_v1_0/core_config.tcl @@ -0,0 +1,37 @@ +set display_name {AXI4-Stream Histogram} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.} +core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::add_bus_interface BRAM_PORTA $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE master $bus +foreach {logical physical} { + RST bram_porta_rst + CLK bram_porta_clk + ADDR bram_porta_addr + DIN bram_porta_wrdata + DOUT bram_porta_rddata + WE bram_porta_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_porta_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTA $parameter diff --git a/cores/axis_histogram_v1_1/axis_histogram.vhd b/cores/axis_histogram_v1_1/axis_histogram.vhd new file mode 100644 index 0000000..922785d --- /dev/null +++ b/cores/axis_histogram_v1_1/axis_histogram.vhd @@ -0,0 +1,141 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_histogram is + generic ( + AXIS_TDATA_WIDTH: natural := 16; + BRAM_DATA_WIDTH : natural := 32; + BRAM_ADDR_WIDTH : natural := 14; + CNTR_WIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data : in std_logic_vector(CNTR_WIDTH-1 downto 0); + sts_data : out std_logic_vector(CNTR_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- BRAM port + bram_porta_clk : out std_logic; + bram_porta_rst : out std_logic; + bram_porta_addr : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_we : out std_logic + ); +end axis_histogram; + +architecture rtl of axis_histogram is + + type state_t is ( + ST_IDLE, + ST_WRITE_ZEROS, + ST_READ_ADDR, + ST_DELAY1, + ST_INC_DATA, + ST_DELAY2 +); +signal state_reg, state_next : state_t; + +signal cntr_reg, cntr_next : unsigned(CNTR_WIDTH-1 downto 0); +signal comp_reg, comp_next : std_logic; + +signal addr_reg, addr_next : std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); +signal data_reg, data_next : std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); +signal tready_reg, tready_next : std_logic; +signal wren_reg, wren_next : std_logic; +signal wren_s : std_logic; + +begin + + sts_data <= std_logic_vector(cntr_reg); + s_axis_tready <= tready_reg; + + bram_porta_clk <= aclk; + bram_porta_rst <= not aresetn; + bram_porta_addr <= addr_reg when (wren_reg = '1') else + s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata <= data_reg; + bram_porta_we <= wren_reg; + + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + comp_reg <= '0'; + cntr_reg <= (others => '0'); + addr_reg <= (others => '0'); + data_reg <= (others => '0'); + tready_reg <= '0'; + wren_reg <= '0'; + else + state_reg <= state_next; + comp_reg <= comp_next; + cntr_reg <= cntr_next; + addr_reg <= addr_next; + data_reg <= data_next; + tready_reg <= tready_next; + wren_reg <= wren_next; + end if; + end if; + end process; + + comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else '1'; + + cntr_next <= cntr_reg + 1 when ((comp_reg = '1') and (tready_reg = '1')) else + --(others => '0') when (comp_reg = '0') else --reset + cntr_reg; + wren_s <= '1' when (bram_porta_rddata = (bram_porta_rddata'range => '1')) else + '0'; + + --Next state logic + process(state_reg, addr_reg, s_axis_tvalid, comp_reg) + begin + state_next <= state_reg; + addr_next <= addr_reg; + data_next <= data_reg; + tready_next <= tready_reg; + wren_next <= wren_reg; + + case state_reg is + when ST_IDLE => + addr_next <= (others => '0'); + data_next <= (others => '0'); + wren_next <= '1'; + state_next <= ST_WRITE_ZEROS; + when ST_WRITE_ZEROS => + addr_next <= std_logic_vector(unsigned(addr_reg) + 1); + if (addr_reg = (addr_reg'range => '1')) then + tready_next <= '1'; + wren_next <= '0'; + state_next <= ST_READ_ADDR; + end if; + when ST_READ_ADDR => + if (s_axis_tvalid = '1') and (comp_reg = '1') then + addr_next <= s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0); + tready_next <= '0'; + state_next <= ST_DELAY1; + end if; + when ST_DELAY1 => + state_next <= ST_INC_DATA; + when ST_INC_DATA => + data_next <= std_logic_vector(unsigned(bram_porta_rddata) + 1); + wren_next <= not wren_s; --(and bram_porta_rddata); + state_next <= ST_DELAY2; + when ST_DELAY2 => + tready_next <= '1'; + wren_next <= '0'; + state_next <= ST_READ_ADDR; + end case; + end process; + +end rtl; diff --git a/cores/axis_histogram_v1_1/core_config.tcl b/cores/axis_histogram_v1_1/core_config.tcl new file mode 100644 index 0000000..82631de --- /dev/null +++ b/cores/axis_histogram_v1_1/core_config.tcl @@ -0,0 +1,37 @@ +set display_name {AXI4-Stream Histogram v1.1} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.} +core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter + +set bus [ipx::add_bus_interface BRAM_PORTA $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE master $bus +foreach {logical physical} { + RST bram_porta_rst + CLK bram_porta_clk + ADDR bram_porta_addr + DIN bram_porta_wrdata + DOUT bram_porta_rddata + WE bram_porta_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_porta_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTA $parameter diff --git a/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd b/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd new file mode 100644 index 0000000..132f961 --- /dev/null +++ b/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd @@ -0,0 +1,417 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 10; + SUBTRIG_ARRAY_LENGTH : natural := 3 +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); +-- pwr_enA : out std_logic; +-- data_out : out std_logic_vector(2**W-1 downto 0); +-- pfifo_status : in std_logic_vector(2 downto 0); +-- ptemperatura : in std_logic_vector(15 downto 0); +-- ppresion : in std_logic_vector(15 downto 0); +-- phora : in std_logic_vector(7 downto 0); +-- pminutos : in std_logic_vector(7 downto 0); +-- psegundos : in std_logic_vector(7 downto 0); +-- latitude1_port : in std_logic_vector(7 downto 0); +-- latitude2_port : in std_logic_vector(7 downto 0); +-- latitude3_port : in std_logic_vector(7 downto 0); +-- latitude4_port : in std_logic_vector(7 downto 0); +-- longitude1_port : in std_logic_vector(7 downto 0); +-- longitude2_port : in std_logic_vector(7 downto 0); +-- longitude3_port : in std_logic_vector(7 downto 0); +-- longitude4_port : in std_logic_vector(7 downto 0); +-- ellipsoid1_port : in std_logic_vector(7 downto 0); +-- ellipsoid2_port : in std_logic_vector(7 downto 0); +-- ellipsoid3_port : in std_logic_vector(7 downto 0); +-- ellipsoid4_port : in std_logic_vector(7 downto 0); +-- num_vis_sat_port : in std_logic_vector(7 downto 0); +-- num_track_sat_port : in std_logic_vector(7 downto 0); +-- rsf_port : in std_logic_vector(7 downto 0) + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0); + adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + + array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); +------------------------------------------------------------------------------------------------------ + +------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + +----------------------------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + + tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + +---------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + +---------------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd b/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd new file mode 100644 index 0000000..132f961 --- /dev/null +++ b/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd @@ -0,0 +1,417 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 10; + SUBTRIG_ARRAY_LENGTH : natural := 3 +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); +-- pwr_enA : out std_logic; +-- data_out : out std_logic_vector(2**W-1 downto 0); +-- pfifo_status : in std_logic_vector(2 downto 0); +-- ptemperatura : in std_logic_vector(15 downto 0); +-- ppresion : in std_logic_vector(15 downto 0); +-- phora : in std_logic_vector(7 downto 0); +-- pminutos : in std_logic_vector(7 downto 0); +-- psegundos : in std_logic_vector(7 downto 0); +-- latitude1_port : in std_logic_vector(7 downto 0); +-- latitude2_port : in std_logic_vector(7 downto 0); +-- latitude3_port : in std_logic_vector(7 downto 0); +-- latitude4_port : in std_logic_vector(7 downto 0); +-- longitude1_port : in std_logic_vector(7 downto 0); +-- longitude2_port : in std_logic_vector(7 downto 0); +-- longitude3_port : in std_logic_vector(7 downto 0); +-- longitude4_port : in std_logic_vector(7 downto 0); +-- ellipsoid1_port : in std_logic_vector(7 downto 0); +-- ellipsoid2_port : in std_logic_vector(7 downto 0); +-- ellipsoid3_port : in std_logic_vector(7 downto 0); +-- ellipsoid4_port : in std_logic_vector(7 downto 0); +-- num_vis_sat_port : in std_logic_vector(7 downto 0); +-- num_track_sat_port : in std_logic_vector(7 downto 0); +-- rsf_port : in std_logic_vector(7 downto 0) + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0); + adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + + array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); +------------------------------------------------------------------------------------------------------ + +------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + +----------------------------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + + tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + +---------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + +---------------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_0/core_config.tcl b/cores/axis_lago_trigger_v1_0/core_config.tcl new file mode 100644 index 0000000..d7a1051 --- /dev/null +++ b/cores/axis_lago_trigger_v1_0/core_config.tcl @@ -0,0 +1,25 @@ +set display_name {AXI4-Stream LAGO Trigger v1r0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.} +core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.} +core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.} +core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter + diff --git a/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd b/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd new file mode 100644 index 0000000..8d357e1 --- /dev/null +++ b/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd @@ -0,0 +1,413 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 10; + SUBTRIG_ARRAY_LENGTH : natural := 3 +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); + temp_i : in std_logic_vector(24-1 downto 0); + pressure_i : in std_logic_vector(24-1 downto 0); + time_i : in std_logic_vector(24-1 downto 0); + date_i : in std_logic_vector(24-1 downto 0); + latitude_i : in std_logic_vector(24-1 downto 0); + longitude_i : in std_logic_vector(24-1 downto 0); + altitude_i : in std_logic_vector(24-1 downto 0); + satellites_i : in std_logic_vector(24-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0); + adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + + array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "000" & temp_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "000" & pressure_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & time_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & altitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & date_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & satellites_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); +------------------------------------------------------------------------------------------------------ + +------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + +----------------------------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + + tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + +---------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + +---------------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd b/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd new file mode 100644 index 0000000..8d357e1 --- /dev/null +++ b/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd @@ -0,0 +1,413 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 10; + SUBTRIG_ARRAY_LENGTH : natural := 3 +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); + temp_i : in std_logic_vector(24-1 downto 0); + pressure_i : in std_logic_vector(24-1 downto 0); + time_i : in std_logic_vector(24-1 downto 0); + date_i : in std_logic_vector(24-1 downto 0); + latitude_i : in std_logic_vector(24-1 downto 0); + longitude_i : in std_logic_vector(24-1 downto 0); + altitude_i : in std_logic_vector(24-1 downto 0); + satellites_i : in std_logic_vector(24-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0); + adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + + array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "000" & temp_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "000" & pressure_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & time_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & altitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & date_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & satellites_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + +-- array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); +-- array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); +-- array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); +-- array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); +-- array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); +-- array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); +-- array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); +-- array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); +-- array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); +-- array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); +------------------------------------------------------------------------------------------------------ + +------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + +----------------------------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + + tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + +---------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + +---------------------------------------------------------------------------------------------------------------- + +---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_1/core_config.tcl b/cores/axis_lago_trigger_v1_1/core_config.tcl new file mode 100644 index 0000000..3e7f5b3 --- /dev/null +++ b/cores/axis_lago_trigger_v1_1/core_config.tcl @@ -0,0 +1,25 @@ +set display_name {AXI4-Stream LAGO Trigger v1r1} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.} +core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.} +core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.} +core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter + diff --git a/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd b/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd new file mode 100644 index 0000000..b8886c0 --- /dev/null +++ b/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd @@ -0,0 +1,472 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 12; + SUBTRIG_ARRAY_LENGTH : natural := 3 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); + temp_i : in std_logic_vector(24-1 downto 0); + pressure_i : in std_logic_vector(24-1 downto 0); + time_i : in std_logic_vector(24-1 downto 0); + date_i : in std_logic_vector(24-1 downto 0); + latitude_i : in std_logic_vector(24-1 downto 0); + longitude_i : in std_logic_vector(24-1 downto 0); + altitude_i : in std_logic_vector(24-1 downto 0); + satellites_i : in std_logic_vector(24-1 downto 0); + scaler_a_i : in std_logic_vector(32-1 downto 0); + scaler_b_i : in std_logic_vector(32-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic + ); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + + --Trigger scaler signals + signal scaler_a_cnt_reg, scaler_a_cnt_next : std_logic_vector(32-1 downto 0); + signal scaler_b_cnt_reg, scaler_b_cnt_next : std_logic_vector(32-1 downto 0); + signal scaler_a_max_tick, scaler_b_max_tick: std_logic; + + --Trigger scaler signals + signal rate_a_cnt_reg, rate_a_cnt_next : std_logic_vector(24-1 downto 0); + signal rate_b_cnt_reg, rate_b_cnt_next : std_logic_vector(24-1 downto 0); + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0); + adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic + + array_pps_next(METADATA_ARRAY_LENGTH-1) <= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + array_pps_next(METADATA_ARRAY_LENGTH-2) <= "1" & "1000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-3) <= "1" & "1001" & "000" & temp_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-4) <= "1" & "1010" & "000" & pressure_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-5) <= "1" & "1011" & "000" & time_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-6) <= "1" & "1100" & "000" & latitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-7) <= "1" & "1100" & "001" & longitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-8) <= "1" & "1100" & "010" & altitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-9) <= "1" & "1100" & "011" & date_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-10)<= "1" & "1100" & "100" & satellites_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-11)<= "1" & "1101" & "000" & rate_a_cnt_reg when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-11); + array_pps_next(METADATA_ARRAY_LENGTH-12)<= "1" & "1110" & "000" & rate_b_cnt_reg when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-12); + + ------------------------------------------------------------------------------------------------------ + + ------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + + ----------------------------------------------------------------------------------------------------- + --rate counter + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + rate_a_cnt_reg <= (others => '0'); + rate_b_cnt_reg <= (others => '0'); + else + rate_a_cnt_reg <= rate_a_cnt_next; + rate_b_cnt_reg <= rate_b_cnt_next; + end if; + end if; + end process; + + --next state logic + rate_a_cnt_next <= std_logic_vector(unsigned(rate_a_cnt_reg) + 1) when scaler_a_max_tick = '1' else + (others => '0') when pps_i = '1' else + rate_a_cnt_reg; + + rate_b_cnt_next <= std_logic_vector(unsigned(rate_b_cnt_reg) + 1) when scaler_b_max_tick = '1' else + (others => '0') when pps_i = '1' else + rate_b_cnt_reg; + ----------------------------------------------------------------------------------------------------- + ----------------------------------------------------------------------------------------------------- + --trigger scaler + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + scaler_a_cnt_reg <= (others => '0'); + scaler_b_cnt_reg <= (others => '0'); + else + scaler_a_cnt_reg <= scaler_a_cnt_next; + scaler_b_cnt_reg <= scaler_b_cnt_next; + end if; + end if; + end process; + + --next state logic + scaler_a_cnt_next <= std_logic_vector(unsigned(scaler_a_cnt_reg) + 1) when tr1_s = '1' else + (others => '0') when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else + scaler_a_cnt_reg; + + scaler_a_max_tick <= '1' when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else '0'; + + scaler_b_cnt_next <= std_logic_vector(unsigned(scaler_b_cnt_reg) + 1) when tr2_s = '1' else + (others => '0') when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else + scaler_b_cnt_reg; + + scaler_b_max_tick <= '1' when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else '0'; + ----------------------------------------------------------------------------------------------------- + + ----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(10)(adc_dat_a_reg(10)'left) = trig_lvl_a(trig_lvl_a'left)) and + (signed(adc_dat_a_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(10)(adc_dat_b_reg(10)'left) = trig_lvl_b(trig_lvl_b'left)) and + (signed(adc_dat_b_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + --tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + tr_s <= '1' when ((scaler_a_max_tick = '1') or (scaler_b_max_tick = '1')) else '0'; + + tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + + ---------------------------------------------------------------------------------------------------------- + + ---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + + ---------------------------------------------------------------------------------------------------------------- + + ---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_2/core_config.tcl b/cores/axis_lago_trigger_v1_2/core_config.tcl new file mode 100644 index 0000000..5df40a5 --- /dev/null +++ b/cores/axis_lago_trigger_v1_2/core_config.tcl @@ -0,0 +1,25 @@ +set display_name {AXI4-Stream LAGO Trigger v1r2} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.} +core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.} +core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.} +core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter + diff --git a/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd b/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd new file mode 100644 index 0000000..7f1a593 --- /dev/null +++ b/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd @@ -0,0 +1,509 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_lago_trigger is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + -- data arrays bit numbers + ADC_DATA_WIDTH : natural := 14; + DATA_ARRAY_LENGTH : natural := 20; + METADATA_ARRAY_LENGTH : natural := 12; + SUBTRIG_ARRAY_LENGTH : natural := 3 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + trig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + trig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_a_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + subtrig_lvl_b_i : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + pps_i : in std_logic; + clk_cnt_pps_i : in std_logic_vector(27-1 downto 0); + temp_i : in std_logic_vector(24-1 downto 0); + pressure_i : in std_logic_vector(24-1 downto 0); + time_i : in std_logic_vector(24-1 downto 0); + date_i : in std_logic_vector(24-1 downto 0); + latitude_i : in std_logic_vector(24-1 downto 0); + longitude_i : in std_logic_vector(24-1 downto 0); + altitude_i : in std_logic_vector(24-1 downto 0); + satellites_i : in std_logic_vector(24-1 downto 0); + scaler_a_i : in std_logic_vector(32-1 downto 0); + scaler_b_i : in std_logic_vector(32-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic + ); +end axis_lago_trigger; + +architecture rtl of axis_lago_trigger is + + constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH; + + --ADC related signals + type adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t; + signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t; + + type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_pps_reg, array_pps_next : array_pps_t; + + type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) + of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal array_scalers_reg, array_scalers_next : array_scalers_t; + + --Trigger related signals + --Triggers + signal tr1_s, tr2_s, tr_s : std_logic; + --Sub-Triggers + signal subtr1_s, subtr2_s, subtr_s : std_logic; + + signal tr_status_reg, tr_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + signal trig_cnt_reg, trig_cnt_next : std_logic_vector(30-1 downto 0); + + --Charge signals + signal charge1_reg, charge1_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + signal charge2_reg, charge2_next : unsigned(ADC_DATA_WIDTH-1 downto 0); + + --FSM signals + type state_t is (ST_IDLE, + ST_ATT_TR, + ST_SEND_TR_STATUS, + ST_SEND_CNT_STATUS, + ST_ATT_SUBTR, + ST_ATT_PPS); + signal state_reg, state_next: state_t; + + signal wr_count_reg, wr_count_next : unsigned(7 downto 0); + signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal status : std_logic_vector(2 downto 0); + + signal axis_tready_reg, axis_tready_next : std_logic; + signal axis_tvalid_reg, axis_tvalid_next : std_logic; + + signal trig_lvl_a, trig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_dat_a, adc_dat_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_reg_a, adc_next_a : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + signal adc_reg_b, adc_next_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); + + --Trigger scaler signals + signal scaler_a_cnt_reg, scaler_a_cnt_next : std_logic_vector(32-1 downto 0); + signal scaler_b_cnt_reg, scaler_b_cnt_next : std_logic_vector(32-1 downto 0); + signal scaler_a_max_tick, scaler_b_max_tick: std_logic; + + --Trigger scaler signals + signal rate_a_cnt_reg, rate_a_cnt_next : std_logic_vector(24-1 downto 0); + signal rate_b_cnt_reg, rate_b_cnt_next : std_logic_vector(24-1 downto 0); + signal tr11_s_dly_reg, tr11_s_dly_next : std_logic; + signal tr21_s_dly_reg, tr21_s_dly_next : std_logic; + +begin + + trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0); + subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0); + + adc_dat_a <= adc_reg_a; + adc_dat_b <= adc_reg_b; + + --input registers + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_reg_a <= (others => '0'); + adc_reg_b <= (others => '0'); + else + adc_reg_a <= adc_next_a; + adc_reg_b <= adc_next_b; + end if; + end if; + end process; + --next state logic + adc_next_a <= ((PADDING_WIDTH-1) downto 0 => + s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & + s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) + when ((axis_tready_reg = '1') and (s_axis_tvalid = '1')) else + adc_reg_a; + adc_next_b <= ((PADDING_WIDTH-1) downto 0 => + s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & + s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto + AXIS_TDATA_WIDTH/2) when ((axis_tready_reg = '1') and (s_axis_tvalid = '1')) else + adc_reg_b; + + + -- data registers for a second + process(aclk) + begin + for i in METADATA_ARRAY_LENGTH-1 downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + array_pps_reg(i) <= (others => '0'); + else + array_pps_reg(i) <= array_pps_next(i); + end if; + end if; + end loop; + end process; + --next state logic + + array_pps_next(METADATA_ARRAY_LENGTH-1) <= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1); + array_pps_next(METADATA_ARRAY_LENGTH-2) <= "1" & "1000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2); + array_pps_next(METADATA_ARRAY_LENGTH-3) <= "1" & "1001" & "000" & temp_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3); + array_pps_next(METADATA_ARRAY_LENGTH-4) <= "1" & "1010" & "000" & pressure_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4); + array_pps_next(METADATA_ARRAY_LENGTH-5) <= "1" & "1011" & "000" & time_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5); + array_pps_next(METADATA_ARRAY_LENGTH-6) <= "1" & "1100" & "000" & latitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6); + array_pps_next(METADATA_ARRAY_LENGTH-7) <= "1" & "1100" & "001" & longitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7); + array_pps_next(METADATA_ARRAY_LENGTH-8) <= "1" & "1100" & "010" & altitude_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8); + array_pps_next(METADATA_ARRAY_LENGTH-9) <= "1" & "1100" & "011" & date_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9); + array_pps_next(METADATA_ARRAY_LENGTH-10)<= "1" & "1100" & "100" & satellites_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10); + array_pps_next(METADATA_ARRAY_LENGTH-11)<= "1" & "1101" & "000" & rate_a_cnt_reg when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-11); + array_pps_next(METADATA_ARRAY_LENGTH-12)<= "1" & "1110" & "000" & rate_b_cnt_reg when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-12); + + ------------------------------------------------------------------------------------------------------ + + ------------------------------------------------------------------------------------------------------ + --data acquisition for each channel + process(aclk) + begin + for i in (DATA_ARRAY_LENGTH-1) downto 0 loop + if (rising_edge(aclk)) then + if (aresetn = '0') then + adc_dat_a_reg(i) <= (others=>'0'); + adc_dat_b_reg(i) <= (others=>'0'); + else + adc_dat_a_reg(i) <= adc_dat_a_next(i); + adc_dat_b_reg(i) <= adc_dat_b_next(i); + end if; + end if; + -- next state logic + if (i = (DATA_ARRAY_LENGTH-1)) then + adc_dat_a_next(i) <= adc_dat_a; + adc_dat_b_next(i) <= adc_dat_b; + else + adc_dat_a_next(i) <= adc_dat_a_reg(i+1); + adc_dat_b_next(i) <= adc_dat_b_reg(i+1); + end if; + end loop; + end process; + + ----------------------------------------------------------------------------------------------------- + --rate counter + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + rate_a_cnt_reg <= (others => '0'); + rate_b_cnt_reg <= (others => '0'); + else + rate_a_cnt_reg <= rate_a_cnt_next; + rate_b_cnt_reg <= rate_b_cnt_next; + end if; + end if; + end process; + + --next state logic + rate_a_cnt_next <= std_logic_vector(unsigned(rate_a_cnt_reg) + 1) when scaler_a_max_tick = '1' else + (others => '0') when pps_i = '1' else + rate_a_cnt_reg; + + rate_b_cnt_next <= std_logic_vector(unsigned(rate_b_cnt_reg) + 1) when scaler_b_max_tick = '1' else + (others => '0') when pps_i = '1' else + rate_b_cnt_reg; + ----------------------------------------------------------------------------------------------------- + ----------------------------------------------------------------------------------------------------- + --trigger scaler + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + scaler_a_cnt_reg <= (others => '0'); + scaler_b_cnt_reg <= (others => '0'); + tr11_s_dly_reg <= '0'; + tr21_s_dly_reg <= '0'; + else + scaler_a_cnt_reg <= scaler_a_cnt_next; + scaler_b_cnt_reg <= scaler_b_cnt_next; + tr11_s_dly_reg <= tr11_s_dly_next; + tr21_s_dly_reg <= tr21_s_dly_next; + end if; + end if; + end process; + + --next state logic + scaler_a_cnt_next <= std_logic_vector(unsigned(scaler_a_cnt_reg) + 1) when tr1_s = '1' else + (others => '0') when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else + scaler_a_cnt_reg; + tr11_s_dly_next <= '1' when tr1_s = '1' else '0'; + + scaler_a_max_tick <= '1' when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else '0'; + + scaler_b_cnt_next <= std_logic_vector(unsigned(scaler_b_cnt_reg) + 1) when tr2_s = '1' else + (others => '0') when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else + scaler_b_cnt_reg; + tr21_s_dly_next <= '1' when tr2_s = '1' else '0'; + + scaler_b_max_tick <= '1' when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else '0'; + ----------------------------------------------------------------------------------------------------- + + ----------------------------------------------------------------------------------------------------- + --trigger + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + tr_status_reg <= (others => '0'); + cnt_status_reg <= (others => '0'); + trig_cnt_reg <= (others => '0'); + else + tr_status_reg <= tr_status_next; + cnt_status_reg <= cnt_status_next; + trig_cnt_reg <= trig_cnt_next; + end if; + end if; + end process; + + + -- The trigger is at bin 4 because we loose a clock pulse in the state machine + -- next state logic + tr1_s <= '1' when ((adc_dat_a_reg(10)(adc_dat_a_reg(10)'left) = trig_lvl_a(trig_lvl_a'left)) and + (signed(adc_dat_a_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + tr2_s <= '1' when ((adc_dat_b_reg(10)(adc_dat_b_reg(10)'left) = trig_lvl_b(trig_lvl_b'left)) and + (signed(adc_dat_b_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and + (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else + '0'; + + --tr_s <= '1' when ((tr1_s = '1') or (tr2_s = '1')) else '0'; + tr_s <= '1' when ((scaler_a_max_tick = '1') or (scaler_b_max_tick = '1')) else '0'; + + --tr_status_next <= "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else + tr_status_next <= "010" & tr21_s_dly_reg & tr11_s_dly_reg & clk_cnt_pps_i when (tr_s = '1') else + tr_status_reg; + cnt_status_next <= "10" & trig_cnt_reg when (tr_s = '1') else + cnt_status_reg; + + trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else + trig_cnt_reg; + + ---------------------------------------------------------------------------------------------------------- + + ---------------------------------------------------------------------------------------------------------- + --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + charge1_reg <= (others => '0'); + charge2_reg <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0'); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0'); + else + charge1_reg <= charge1_next; + charge2_reg <= charge2_next; + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2); + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3); + end if; + end if; + end process; + -- next state logic + subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and + signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or + (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and + (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and + signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and + signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else + '0'; + subtr_s <= '1' when ((subtr1_s = '1') or (subtr2_s = '1')) else '0'; + + charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right; + charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right; + + array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1); + array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel + array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else + array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too + + ---------------------------------------------------------------------------------------------------------------- + + ---------------------------------------------------------------------------------------------------------------- + -- FSM controlling all + --================================================================ + -- state and data registers + --================================================================ + process (aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + state_reg <= ST_IDLE; + wr_count_reg <= (others => '0'); + data_to_fifo_reg <= (others => '0'); + axis_tvalid_reg <= '0'; + axis_tready_reg <= '0'; + else + state_reg <= state_next; + wr_count_reg <= wr_count_next; + data_to_fifo_reg <= data_to_fifo_next; + axis_tvalid_reg <= axis_tvalid_next; + axis_tready_reg <= axis_tready_next; + end if; + end if; + end process; + --================================================================= + --next-state logic & data path functional units/routing + --================================================================= + process(state_reg, status, wr_count_reg) + begin + state_next <= state_reg; -- default + wr_count_next <= (others => '0'); -- wr_count_reg; + data_to_fifo_next <= data_to_fifo_reg; -- default + axis_tvalid_next <= '0'; -- default disable write + axis_tready_next <= '1'; -- always ready + case state_reg is + when ST_IDLE => + if (m_axis_tready = '1') then + case status is + when "001" | "011" | "101" | "111" => -- priority is for PPS data every second + state_next <= ST_ATT_PPS; + when "100" | "110" => + state_next <= ST_ATT_TR; + when "010" => + state_next <= ST_ATT_SUBTR; + when others => --"000" + state_next <= ST_IDLE; + end case; + else + state_next <= ST_IDLE; + end if; + + --we send adc data because we have a trigger + when ST_ATT_TR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)); + data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0); + --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg); + if (wr_count_reg = DATA_ARRAY_LENGTH-1) then + state_next <= ST_SEND_TR_STATUS; + else + state_next <= ST_ATT_TR; + end if; + else + state_next <= ST_ATT_TR; + end if; + + when ST_SEND_TR_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= tr_status_reg; + --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30)); + state_next <= ST_SEND_CNT_STATUS; + else + state_next <= ST_SEND_TR_STATUS; + end if; + + when ST_SEND_CNT_STATUS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + data_to_fifo_next <= cnt_status_reg; + --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30)); + state_next <= ST_IDLE; + else + state_next <= ST_SEND_CNT_STATUS; + end if; + + when ST_ATT_SUBTR => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg)); + if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_SUBTR; + end if; + else + state_next <= ST_ATT_SUBTR; + end if; + + when ST_ATT_PPS => + axis_tready_next <= '0'; + axis_tvalid_next <= '1'; + if (m_axis_tready = '1') then + wr_count_next <= wr_count_reg + 1; + data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg)); + if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then + state_next <= ST_IDLE; + else + state_next <= ST_ATT_PPS; + end if; + else + state_next <= ST_ATT_PPS; + end if; + end case; + end process; + + status <= tr_s & subtr_s & pps_i; + s_axis_tready <= axis_tready_reg; + m_axis_tdata <= data_to_fifo_reg; + m_axis_tvalid <= axis_tvalid_reg; + +end architecture rtl; + diff --git a/cores/axis_lago_trigger_v1_3/core_config.tcl b/cores/axis_lago_trigger_v1_3/core_config.tcl new file mode 100644 index 0000000..725cd3a --- /dev/null +++ b/cores/axis_lago_trigger_v1_3/core_config.tcl @@ -0,0 +1,25 @@ +set display_name {AXI4-Stream LAGO Trigger v1r3} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.} +core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.} +core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.} +core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter + diff --git a/cores/axis_packetizer_v1_0/axis_packetizer.vhd b/cores/axis_packetizer_v1_0/axis_packetizer.vhd new file mode 100644 index 0000000..dd8e5ec --- /dev/null +++ b/cores/axis_packetizer_v1_0/axis_packetizer.vhd @@ -0,0 +1,83 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_packetizer is + generic ( + AXIS_TDATA_WIDTH : natural := 32; + CNTR_WIDTH : natural := 32; + CONTINUOUS : string := "FALSE" +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + -- Configuration bits + cfg_data : in std_logic_vector(CNTR_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + --Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tlast : out std_logic +); +end axis_packetizer; + +architecture rtl of axis_packetizer is + + signal int_cntr_reg, int_cntr_next : unsigned(CNTR_WIDTH-1 downto 0); + signal int_enbl_reg, int_enbl_next : std_logic; + + signal int_comp_wire, int_tvalid_wire, int_tlast_wire : std_logic; + +begin + + process(aclk) + begin + if (rising_edge(aclk)) then + if (aresetn = '0') then + int_cntr_reg <= (others => '0'); + int_enbl_reg <= '0'; + else + int_cntr_reg <= int_cntr_next; + int_enbl_reg <= int_enbl_next; + end if; + end if; + end process; + + int_comp_wire <= '1' when (int_cntr_reg < unsigned(cfg_data)) else '0'; + int_tvalid_wire <= '1' when (int_enbl_reg = '1') and (s_axis_tvalid = '1') else '0'; + int_tlast_wire <= '1' when (int_comp_wire = '0') else '0'; + + CONTINUOUS_G: if (CONTINUOUS = "TRUE") generate + begin + int_cntr_next <= int_cntr_reg + 1 when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_comp_wire = '1') else + (others => '0') when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_tlast_wire = '1') else + int_cntr_reg; + + int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else int_enbl_reg; + end generate; + + STOP_G: if (CONTINUOUS = "FALSE") generate + begin + int_cntr_next <= int_cntr_reg + 1 when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_comp_wire = '1') else + int_cntr_reg; + + int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else + '0' when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_tlast_wire = '1') else + int_enbl_reg; + end generate; + + s_axis_tready <= '1' when (int_enbl_reg = '1') and (m_axis_tready = '1') else '0'; + m_axis_tdata <= s_axis_tdata; + m_axis_tvalid <= int_tvalid_wire; + m_axis_tlast <= '1' when (int_enbl_reg = '1') and (int_tlast_wire = '1') else '0'; + +end rtl; diff --git a/cores/axis_packetizer_v1_0/core_config.tcl b/cores/axis_packetizer_v1_0/core_config.tcl new file mode 100644 index 0000000..dc6b23e --- /dev/null +++ b/cores/axis_packetizer_v1_0/core_config.tcl @@ -0,0 +1,22 @@ +set display_name {AXI4-Stream Packetizer} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.} +core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.} +core_parameter CONTINUOUS {CONTINUOUS} {If TRUE, packetizer runs continuously.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter diff --git a/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd b/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd new file mode 100644 index 0000000..55d0535 --- /dev/null +++ b/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd @@ -0,0 +1,80 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity axis_rp_dac is + generic ( + DAC_DATA_WIDTH : natural := 14; + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + -- PLL signals + aclk : in std_logic; + ddr_clk : in std_logic; + locked : in std_logic; + + -- DAC signals + dac_clk : out std_logic; + dac_rst : out std_logic; + dac_sel : out std_logic; + dac_wrt : out std_logic; + dac_dat : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) +); +end axis_rp_dac; + +architecture rtl of axis_rp_dac is + + signal int_dat_a_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_dat_b_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_rst_reg : std_logic; + + signal int_dat_a_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_dat_b_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + +begin + int_dat_a_wire <= s_axis_tdata(DAC_DATA_WIDTH-1 downto 0); + int_dat_b_wire <= s_axis_tdata(AXIS_TDATA_WIDTH/2+DAC_DATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + process(aclk) + begin + if rising_edge(aclk) then + if (locked = '0' or s_axis_tvalid = '0') then + int_dat_a_reg <= (others => '0'); + int_dat_b_reg <= (others => '0'); + else + int_dat_a_reg <= int_dat_a_wire(DAC_DATA_WIDTH-1) & not int_dat_a_wire(DAC_DATA_WIDTH-2 downto 0); + int_dat_b_reg <= int_dat_b_wire(DAC_DATA_WIDTH-1) & not int_dat_b_wire(DAC_DATA_WIDTH-2 downto 0); + int_rst_reg <= not locked or not s_axis_tvalid; + end if; + end if; + end process; + + ODDR_rst: ODDR port map (Q => dac_rst, D1 => int_rst_reg, D2 => int_rst_reg, C => aclk, CE => '1', R => '0', S => '0'); + ODDR_sel: ODDR port map (Q => dac_sel, D1 => '0', D2 => '1', C => aclk, CE => '1', R => '0', S => '0'); + ODDR_wrt: ODDR port map (Q => dac_wrt, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0'); + ODDR_clk: ODDR port map (Q => dac_clk, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0'); + + DAC_DAT_inst: for j in 0 to DAC_DATA_WIDTH-1 generate + ODDR_inst: ODDR port map( + Q => dac_dat(j), + D1 => int_dat_a_reg(j), + D2 =>int_dat_b_reg(j), + C => aclk, + CE =>'1', + R => '0', + S => '0' + ); + end generate; + + s_axis_tready <= '1'; + +end rtl; diff --git a/cores/axis_rp_dac_v1_0/core_config.tcl b/cores/axis_rp_dac_v1_0/core_config.tcl new file mode 100644 index 0000000..17b73fd --- /dev/null +++ b/cores/axis_rp_dac_v1_0/core_config.tcl @@ -0,0 +1,17 @@ +set display_name {AXI4-Stream Red Pitaya DAC v1.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter DAC_DATA_WIDTH {DAC DATA WIDTH} {Width of the DAC data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter diff --git a/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd b/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd new file mode 100644 index 0000000..c8975cc --- /dev/null +++ b/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd @@ -0,0 +1,81 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity axis_rp_dac is + generic ( + DAC_DATA_WIDTH : natural := 14; + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + -- PLL signals + aclk : in std_logic; + ddr_clk : in std_logic; + wrt_clk : in std_logic; + locked : in std_logic; + + -- DAC signals + dac_clk : out std_logic; + dac_rst : out std_logic; + dac_sel : out std_logic; + dac_wrt : out std_logic; + dac_dat : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tvalid : in std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) +); +end axis_rp_dac; + +architecture rtl of axis_rp_dac is + + signal int_dat_a_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_dat_b_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_rst_reg : std_logic; + + signal int_dat_a_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + signal int_dat_b_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0); + +begin + int_dat_a_wire <= s_axis_tdata(DAC_DATA_WIDTH-1 downto 0); + int_dat_b_wire <= s_axis_tdata(AXIS_TDATA_WIDTH/2+DAC_DATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + process(aclk) + begin + if rising_edge(aclk) then + if (locked = '0' or s_axis_tvalid = '0') then + int_dat_a_reg <= (others => '0'); + int_dat_b_reg <= (others => '0'); + else + int_dat_a_reg <= int_dat_a_wire(DAC_DATA_WIDTH-1) & not int_dat_a_wire(DAC_DATA_WIDTH-2 downto 0); + int_dat_b_reg <= int_dat_b_wire(DAC_DATA_WIDTH-1) & not int_dat_b_wire(DAC_DATA_WIDTH-2 downto 0); + int_rst_reg <= not locked or not s_axis_tvalid; + end if; + end if; + end process; + + ODDR_rst: ODDR port map (Q => dac_rst, D1 => int_rst_reg, D2 => int_rst_reg, C => aclk, CE => '1', R => '0', S => '0'); + ODDR_sel: ODDR port map (Q => dac_sel, D1 => '0', D2 => '1', C => aclk, CE => '1', R => '0', S => '0'); + ODDR_wrt: ODDR port map (Q => dac_wrt, D1 => '0', D2 => '1', C => wrt_clk, CE => '1', R => '0', S => '0'); + ODDR_clk: ODDR port map (Q => dac_clk, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0'); + + DAC_DAT_inst: for j in 0 to DAC_DATA_WIDTH-1 generate + ODDR_inst: ODDR port map( + Q => dac_dat(j), + D1 => int_dat_a_reg(j), + D2 =>int_dat_b_reg(j), + C => aclk, + CE =>'1', + R => '0', + S => '0' + ); + end generate; + + s_axis_tready <= '1'; + +end rtl; diff --git a/cores/axis_rp_dac_v2_0/core_config.tcl b/cores/axis_rp_dac_v2_0/core_config.tcl new file mode 100644 index 0000000..fac0868 --- /dev/null +++ b/cores/axis_rp_dac_v2_0/core_config.tcl @@ -0,0 +1,17 @@ +set display_name {AXI4-Stream Red Pitaya DAC v2.0} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.} +core_parameter DAC_DATA_WIDTH {DAC DATA WIDTH} {Width of the DAC data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE S_AXIS $parameter diff --git a/cores/axis_validator_v1_0/axis_validator.vhd b/cores/axis_validator_v1_0/axis_validator.vhd new file mode 100644 index 0000000..606ae7a --- /dev/null +++ b/cores/axis_validator_v1_0/axis_validator.vhd @@ -0,0 +1,35 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_validator is + generic ( + AXIS_TDATA_WIDTH : natural := 32 + ); + port ( + -- System signals + aclk : in std_logic; + trg_flag : in std_logic; + + -- Slave side + s_axis_tready : out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid : in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic + ); +end axis_validator; + +architecture rtl of axis_validator is + +begin + + s_axis_tready <= m_axis_tready; + m_axis_tdata <= s_axis_tdata; + m_axis_tvalid <= '1' when ((s_axis_tvalid = '1') and (trg_flag = '1')) else + '0'; +end rtl; diff --git a/cores/axis_validator_v1_0/core_config.tcl b/cores/axis_validator_v1_0/core_config.tcl new file mode 100644 index 0000000..5b57b3d --- /dev/null +++ b/cores/axis_validator_v1_0/core_config.tcl @@ -0,0 +1,20 @@ +set display_name {AXI4-Stream Validator} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter diff --git a/cores/axis_variable_v1_0/axis_variable.vhd b/cores/axis_variable_v1_0/axis_variable.vhd new file mode 100644 index 0000000..b79e1db --- /dev/null +++ b/cores/axis_variable_v1_0/axis_variable.vhd @@ -0,0 +1,51 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_variable is + generic ( + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_variable; + +architecture rtl of axis_variable is + + signal int_tdata_reg : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + signal int_tvalid_reg, int_tvalid_next: std_logic; + +begin + + process(aclk) + begin + if (rising_edge(aclk)) then + if(aresetn = '0') then + int_tdata_reg <= (others => '0'); + int_tvalid_reg <= '0'; + else + int_tdata_reg <= cfg_data; + int_tvalid_reg <= int_tvalid_next; + end if; + end if; + end process; + + int_tvalid_next <= '1' when (int_tdata_reg /= cfg_data) else + '0' when (m_axis_tready = '1') and (int_tvalid_reg = '1') else + int_tvalid_reg; + + m_axis_tdata <= int_tdata_reg; + m_axis_tvalid <= int_tvalid_reg; + +end rtl; diff --git a/cores/axis_variable_v1_0/core_config.tcl b/cores/axis_variable_v1_0/core_config.tcl new file mode 100644 index 0000000..70ffb5a --- /dev/null +++ b/cores/axis_variable_v1_0/core_config.tcl @@ -0,0 +1,16 @@ +set display_name {AXI4-Stream Variable} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS $parameter diff --git a/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd b/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd new file mode 100644 index 0000000..cd49b7b --- /dev/null +++ b/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd @@ -0,0 +1,99 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity zero_cross_det is +generic ( + HYST_CONST : natural := 2048; --"00100000000000" + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + aclk : in std_logic; + aresetn : in std_logic; + + det_a_o : out std_logic; + det_b_o : out std_logic; + + -- Slave side + s_axis_tready: out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) +); +end zero_cross_det; + +architecture rtl of zero_cross_det is + +signal sig_a_reg, sig_a_next: std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); +signal sig_b_reg, sig_b_next: std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0); +signal det_a_o_reg, det_a_o_next: std_logic; +signal det_b_o_reg, det_b_o_next: std_logic; +signal hyst_a_low_reg, hyst_a_low_next : std_logic; +signal hyst_a_high_reg, hyst_a_high_next : std_logic; +signal hyst_b_low_reg, hyst_b_low_next : std_logic; +signal hyst_b_high_reg, hyst_b_high_next : std_logic; + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if aresetn = '0' then + sig_a_reg <= (others => '0'); + det_a_o_reg <= '0'; + hyst_a_low_reg <= '0'; + hyst_a_high_reg <= '0'; + + sig_b_reg <= (others => '0'); + det_b_o_reg <= '0'; + hyst_b_low_reg <= '0'; + hyst_b_high_reg <= '0'; + else + sig_a_reg <= sig_a_next; + det_a_o_reg <= det_a_o_next; + hyst_a_low_reg <= hyst_a_low_next; + hyst_a_high_reg <= hyst_a_high_next; + + sig_b_reg <= sig_b_next; + det_b_o_reg <= det_b_o_next; + hyst_b_low_reg <= hyst_b_low_next; + hyst_b_high_reg <= hyst_b_high_next; + end if; + end if; + end process; + + --Next state logic + sig_a_next <= s_axis_tdata(AXIS_TDATA_WIDTH/2-1 downto 0); + + det_a_o_next <= '1' when (sig_a_reg(sig_a_reg'left) = '1' and sig_a_next(sig_a_next'left) = '0' and hyst_a_low_reg = '1') else + '0' when (sig_a_reg(sig_a_reg'left) = '0' and sig_a_next(sig_a_next'left) = '1' and hyst_a_high_reg = '1') else + det_a_o_reg; + + hyst_a_low_next <= '1' when (signed(sig_a_next) < (to_signed(-HYST_CONST, AXIS_TDATA_WIDTH/2))) else + '0' when (sig_a_reg(sig_a_reg'left) = '1' and sig_a_next(sig_a_next'left) = '0' and hyst_a_low_reg = '1') else + hyst_a_low_reg; + + hyst_a_high_next <= '1' when (signed(sig_a_next) > (to_signed(HYST_CONST, AXIS_TDATA_WIDTH/2))) else + '0' when (sig_a_reg(sig_a_reg'left) = '0' and sig_a_next(sig_a_next'left) = '1' and hyst_a_high_reg = '1') else + hyst_a_high_reg; + + det_a_o <= det_a_o_reg; + + sig_b_next <= s_axis_tdata(AXIS_TDATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2); + + det_b_o_next <= '1' when (sig_b_reg(sig_b_reg'left) = '1' and sig_b_next(sig_b_next'left) = '0' and hyst_b_low_reg = '1') else + '0' when (sig_b_reg(sig_b_reg'left) = '0' and sig_b_next(sig_b_next'left) = '1' and hyst_b_high_reg = '1') else + det_b_o_reg; + + hyst_b_low_next <= '1' when (signed(sig_b_next) < (to_signed(-HYST_CONST, AXIS_TDATA_WIDTH/2))) else + '0' when (sig_b_reg(sig_b_reg'left) = '1' and sig_b_next(sig_b_next'left) = '0' and hyst_b_low_reg = '1') else + hyst_b_low_reg; + + hyst_b_high_next <= '1' when (signed(sig_b_next) > (to_signed(HYST_CONST, AXIS_TDATA_WIDTH/2))) else + '0' when (sig_b_reg(sig_b_reg'left) = '0' and sig_b_next(sig_b_next'left) = '1' and hyst_b_high_reg = '1') else + hyst_b_high_reg; + + det_b_o <= det_b_o_reg; + + + s_axis_tready <= '1'; + +end rtl; diff --git a/cores/axis_zero_crossing_det_v1_0/core_config.tcl b/cores/axis_zero_crossing_det_v1_0/core_config.tcl new file mode 100644 index 0000000..ebd926f --- /dev/null +++ b/cores/axis_zero_crossing_det_v1_0/core_config.tcl @@ -0,0 +1,17 @@ +set display_name {AXI4-Stream Zero Crossing Detector} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.} +core_parameter HYST_CONST {HYSTERISIS CONSTANT} {Hysterisis constant.} + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE S_AXIS $parameter diff --git a/cores/axis_zeroer_v1_0/axis_zeroer.vhd b/cores/axis_zeroer_v1_0/axis_zeroer.vhd new file mode 100644 index 0000000..01f42c0 --- /dev/null +++ b/cores/axis_zeroer_v1_0/axis_zeroer.vhd @@ -0,0 +1,34 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_zeroer is + generic ( + AXIS_TDATA_WIDTH: natural := 32 +); +port ( + -- System signals + aclk : in std_logic; + + -- Slave side + s_axis_tready: out std_logic; + s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + s_axis_tvalid: in std_logic; + + -- Master side + m_axis_tready : in std_logic; + m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0); + m_axis_tvalid : out std_logic +); +end axis_zeroer; + +architecture rtl of axis_zeroer is + +begin + + s_axis_tready <= m_axis_tready; + m_axis_tdata <= s_axis_tdata when (s_axis_tvalid = '1') else (others => '0'); + m_axis_tvalid <= '1'; + +end rtl; diff --git a/cores/axis_zeroer_v1_0/core_config.tcl b/cores/axis_zeroer_v1_0/core_config.tcl new file mode 100644 index 0000000..6074dff --- /dev/null +++ b/cores/axis_zeroer_v1_0/core_config.tcl @@ -0,0 +1,20 @@ +set display_name {AXI4-Stream Zeroer} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.} + +set bus [ipx::get_bus_interfaces -of_objects $core m_axis] +set_property NAME M_AXIS $bus +set_property INTERFACE_MODE master $bus + +set bus [ipx::get_bus_interfaces -of_objects $core s_axis] +set_property NAME S_AXIS $bus +set_property INTERFACE_MODE slave $bus + +set bus [ipx::get_bus_interfaces aclk] +set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF] +set_property VALUE M_AXIS:S_AXIS $parameter diff --git a/cores/bram_counter_v1_0/bram_counter.vhd b/cores/bram_counter_v1_0/bram_counter.vhd new file mode 100644 index 0000000..432426e --- /dev/null +++ b/cores/bram_counter_v1_0/bram_counter.vhd @@ -0,0 +1,77 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bram_counter is + generic ( + BRAM_DATA_WIDTH : natural := 32; + BRAM_ADDR_WIDTH : natural := 14 + ); + port ( + -- System signals + aclk : in std_logic; + aresetn : in std_logic; + + cfg_data : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + + -- BRAM port + bram_porta_clk : out std_logic; + bram_porta_rst : out std_logic; + bram_porta_addr : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_we : out std_logic + ); + +end bram_counter; + +architecture rtl of bram_counter is + + signal cntr_reg, cntr_next : unsigned(BRAM_DATA_WIDTH-1 downto 0); + signal comp_reg, comp_next : std_logic; + signal addr_reg, addr_next : unsigned(BRAM_ADDR_WIDTH-1 downto 0); + signal wren_reg, wren_next : std_logic; + + +begin + + bram_porta_clk <= aclk; + bram_porta_rst <= not aresetn; + bram_porta_addr <= std_logic_vector(addr_reg); + bram_porta_wrdata <= std_logic_vector(cntr_reg); + bram_porta_we <= wren_reg; + + process(aclk) + begin + if (rising_edge(aclk)) then + if(aresetn = '0') then + addr_reg <= (others => '0'); + cntr_reg <= (others => '0'); + comp_reg <= '0'; + wren_reg <= '0'; + else + addr_reg <= addr_next; + cntr_reg <= cntr_next; + comp_reg <= comp_next; + wren_reg <= wren_next; + end if; + end if; + end process; + + wren_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else + '1'; + + comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else + '1'; + + addr_next <= addr_reg + 1 when (comp_reg = '1') else + (others => '0') when (comp_reg = '0') else --reset + addr_reg; + + cntr_next <= cntr_reg + 1 when (comp_reg = '1') else + (others => '0') when (comp_reg = '0') else --reset + cntr_reg; + + +end rtl; diff --git a/cores/bram_counter_v1_0/core_config.tcl b/cores/bram_counter_v1_0/core_config.tcl new file mode 100644 index 0000000..ae4bc72 --- /dev/null +++ b/cores/bram_counter_v1_0/core_config.tcl @@ -0,0 +1,29 @@ +set display_name {BRAM Counter} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.} +core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.} + +set bus [ipx::add_bus_interface BRAM_PORTA $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE master $bus +foreach {logical physical} { + RST bram_porta_rst + CLK bram_porta_clk + ADDR bram_porta_addr + DIN bram_porta_wrdata + DOUT bram_porta_rddata + WE bram_porta_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_porta_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTA $parameter + diff --git a/cores/bram_selector_v1_0/bram_selector.vhd b/cores/bram_selector_v1_0/bram_selector.vhd new file mode 100644 index 0000000..0b1c18b --- /dev/null +++ b/cores/bram_selector_v1_0/bram_selector.vhd @@ -0,0 +1,69 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axis_bram_sel is + generic ( + BRAM_DATA_WIDTH : natural := 32; + BRAM_ADDR_WIDTH : natural := 14 -- 2^11 = 2048 positions + ); + port ( + -- System signals + aclk : in std_logic; + + sel : in std_logic; + + -- BRAM PORT A + bram_porta_clk : in std_logic; + bram_porta_rst : in std_logic; + bram_porta_addr : in std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_porta_wrdata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_rddata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_porta_we : in std_logic; + + -- BRAM PORT B + bram_portb_clk : in std_logic; + bram_portb_rst : in std_logic; + bram_portb_addr : in std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_portb_wrdata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_portb_rddata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_portb_we : in std_logic; + + -- BRAM PORT C + bram_portc_clk : out std_logic; + bram_portc_rst : out std_logic; + bram_portc_addr : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0); + bram_portc_wrdata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_portc_rddata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0); + bram_portc_we : out std_logic + ); +end axis_bram_sel; + +architecture rtl of axis_bram_sel is + +begin + + bram_portc_rst <= bram_porta_rst when (sel = '1') else + bram_portb_rst; + bram_portc_addr <= bram_porta_addr when (sel = '1') else + bram_portb_addr; + bram_portc_wrdata <= bram_porta_wrdata when (sel = '1') else + bram_portb_wrdata; + bram_portc_we <= bram_porta_we when (sel = '1') else + bram_portb_we; + + bram_porta_rddata <= bram_portc_rddata when (sel = '1') else + (others => '0'); + bram_portb_rddata <= bram_portc_rddata when (sel = '0') else + (others => '0'); + + BUFGMUX_inst: BUFGMUX + port map ( + O => bram_portc_clk, -- 1-bit output: Clock output + I0 => bram_portb_clk, -- 1-bit input: Clock input (S=0) + I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1) + S => sel -- 1-bit input: Clock select + ); + +end rtl; diff --git a/cores/bram_selector_v1_0/core_config.tcl b/cores/bram_selector_v1_0/core_config.tcl new file mode 100644 index 0000000..eda9171 --- /dev/null +++ b/cores/bram_selector_v1_0/core_config.tcl @@ -0,0 +1,66 @@ +set display_name {BRAM Selector} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.} +core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.} + +set bus [ipx::add_bus_interface BRAM_PORTA $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE slave $bus +foreach {logical physical} { + RST bram_porta_rst + CLK bram_porta_clk + ADDR bram_porta_addr + DIN bram_porta_wrdata + DOUT bram_porta_rddata + WE bram_porta_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_porta_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTA $parameter + +set bus [ipx::add_bus_interface BRAM_PORTB $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE slave $bus +foreach {logical physical} { + RST bram_portb_rst + CLK bram_portb_clk + ADDR bram_portb_addr + DIN bram_portb_wrdata + DOUT bram_portb_rddata + WE bram_portb_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_portb_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTB $parameter + +set bus [ipx::add_bus_interface BRAM_PORTC $core] +set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus +set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus +set_property INTERFACE_MODE master $bus +foreach {logical physical} { + RST bram_portc_rst + CLK bram_portc_clk + ADDR bram_portc_addr + DIN bram_portc_wrdata + DOUT bram_portc_rddata + WE bram_portc_we +} { + set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus] +} + +set bus [ipx::get_bus_interfaces bram_portc_clk] +set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus] +set_property VALUE BRAM_PORTB $parameter diff --git a/cores/dna_reader_v1_0/core_config.tcl b/cores/dna_reader_v1_0/core_config.tcl new file mode 100644 index 0000000..072eb85 --- /dev/null +++ b/cores/dna_reader_v1_0/core_config.tcl @@ -0,0 +1,6 @@ +set display_name {DNA Reader} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core diff --git a/cores/dna_reader_v1_0/dna_reader.vhd b/cores/dna_reader_v1_0/dna_reader.vhd new file mode 100644 index 0000000..9aa8930 --- /dev/null +++ b/cores/dna_reader_v1_0/dna_reader.vhd @@ -0,0 +1,81 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +entity dna_reader is +port ( + aclk : in std_logic; + aresetn : in std_logic; + + dna_data : out std_logic_vector(56 downto 0) +); +end dna_reader; + +architecture rtl of dna_reader is + + constant CNTR_WIDTH : integer := 16; + constant DATA_WIDTH : integer := 57; + + signal int_enbl_reg, int_enbl_next : std_logic; + signal int_read_reg, int_read_next: std_logic; + signal int_shift_reg, int_shift_next : std_logic; + signal int_cntr_reg, int_cntr_next: unsigned(CNTR_WIDTH-1 downto 0); + signal int_data_reg, int_data_next: std_logic_vector(DATA_WIDTH-1 downto 0); + signal int_comp_wire, int_data_wire: std_logic; + +begin + + int_comp_wire <= '1' when (int_cntr_reg < 64*DATA_WIDTH) else '0'; + + dna_0: DNA_PORT + port map ( + DOUT => int_data_wire, + CLK => int_cntr_reg(5), + DIN => '0', + READ => int_read_reg, + SHIFT => int_shift_reg + ); + + process(aclk) + begin + if rising_edge(aclk) then + if(aresetn = '0') then + int_enbl_reg <= '0'; + int_read_reg <= '0'; + int_shift_reg <= '0'; + int_cntr_reg <= (others => '0'); + int_data_reg <= (others => '0'); + else + int_enbl_reg <= int_enbl_next; + int_read_reg <= int_read_next; + int_shift_reg <= int_shift_next; + int_cntr_reg <= int_cntr_next; + int_data_reg <= int_data_next; + end if; + end if; + end process; + + int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else + '0' when (int_comp_wire = '0') else + int_enbl_reg; + + int_read_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else + '0' when (int_cntr_reg(5 downto 0) = "111111") else + int_read_reg; + + int_data_next <= int_data_reg(DATA_WIDTH-2 downto 0) & int_data_wire when (int_cntr_reg(5 downto 0) = "111111") else + int_data_reg; + + int_cntr_next <= int_cntr_reg + 1 when (int_enbl_reg = '1') else int_cntr_reg; + + int_shift_next <= '0' when (int_comp_wire = '0') else + '1' when (int_cntr_reg(5 downto 0) = "111111") else + int_shift_reg; + + dna_data <= int_data_reg; + +end rtl; diff --git a/cores/int_counter_v1_0/core_config.tcl b/cores/int_counter_v1_0/core_config.tcl new file mode 100644 index 0000000..e74d0bf --- /dev/null +++ b/cores/int_counter_v1_0/core_config.tcl @@ -0,0 +1,7 @@ +set display_name {Interrupt Generator} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + diff --git a/cores/int_counter_v1_0/int_counter.vhd b/cores/int_counter_v1_0/int_counter.vhd new file mode 100644 index 0000000..e483a9d --- /dev/null +++ b/cores/int_counter_v1_0/int_counter.vhd @@ -0,0 +1,38 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity int_counter is + port ( + aclk : in std_logic; + aresetn : in std_logic; + int_o : out std_logic + ); +end int_counter; + +architecture rtl of int_counter is + + signal counter_reg, counter_next : std_logic_vector(30-1 downto 0); + signal int_reg, int_next : std_logic; + +begin + + process(aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + counter_reg <= (others => '0'); + int_reg <= '0'; + else + counter_reg <= counter_next; + int_reg <= int_next; + end if; + end if; + end process; + + counter_next <= std_logic_vector(unsigned(counter_reg) + 1); + int_next <= '1' when (unsigned(counter_reg) = 0) or (unsigned(counter_reg) = 1) or (unsigned(counter_reg) = 2) else '0'; + + int_o <= int_reg; + +end rtl; diff --git a/cores/port_selector_v1_0/core_config.tcl b/cores/port_selector_v1_0/core_config.tcl new file mode 100644 index 0000000..bc9e8a6 --- /dev/null +++ b/cores/port_selector_v1_0/core_config.tcl @@ -0,0 +1,8 @@ +set display_name {Port Selector} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter DOUT_WIDTH {DOUT WIDTH} {Width of the output port.} diff --git a/cores/port_selector_v1_0/port_selector.vhd b/cores/port_selector_v1_0/port_selector.vhd new file mode 100644 index 0000000..2f1ff77 --- /dev/null +++ b/cores/port_selector_v1_0/port_selector.vhd @@ -0,0 +1,30 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity port_selector is +generic( + DOUT_WIDTH : integer := 32 +); +port ( + cfg : in std_logic; + din : in std_logic_vector(2*DOUT_WIDTH-1 downto 0); + dout : out std_logic_vector(DOUT_WIDTH-1 downto 0) + ); +end port_selector; + +architecture rtl of port_selector is + +begin + + process(cfg) + begin + if cfg = '1' then + dout <= din(2*DOUT_WIDTH-1 downto DOUT_WIDTH); + else + dout <= din(DOUT_WIDTH-1 downto 0); + end if; + end process; + +end rtl; diff --git a/cores/ramp_gen_v1_0/core_config.tcl b/cores/ramp_gen_v1_0/core_config.tcl new file mode 100644 index 0000000..b2c5e3b --- /dev/null +++ b/cores/ramp_gen_v1_0/core_config.tcl @@ -0,0 +1,10 @@ +set display_name {Ramp Signal Generator} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + +core_parameter COUNT_NBITS {COUNTER BITS} {Width of the counter in bits.} +core_parameter COUNT_MOD {MODULE OF COUNTER} {Module of the counter.} +core_parameter DATA_BITS {DATA WIDTH} {Width of the data bus.} diff --git a/cores/ramp_gen_v1_0/ramp_gen.vhd b/cores/ramp_gen_v1_0/ramp_gen.vhd new file mode 100644 index 0000000..58e2199 --- /dev/null +++ b/cores/ramp_gen_v1_0/ramp_gen.vhd @@ -0,0 +1,83 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity ramp_gen is + generic( + COUNT_NBITS : integer := 18; -- number of bits of the counter + COUNT_MOD : integer := 200000; -- mod-n + DATA_BITS : integer := 12); -- number of bits for the data + port( + aclk : in std_logic; + aresetn : in std_logic; + data_i : in std_logic_vector(DATA_BITS-1 downto 0); + data_o : out std_logic_vector(DATA_BITS-1 downto 0); + pwm_o : out std_logic; + led_o : out std_logic); +end ramp_gen; + +architecture rtl of ramp_gen is + signal cnt_reg, cnt_next : std_logic_vector(COUNT_NBITS-1 downto 0); + signal in_reg, in_next : std_logic_vector(DATA_BITS-1 downto 0); + signal r_reg, r_next : std_logic_vector(DATA_BITS-1 downto 0); + signal out_reg, out_next : std_logic_vector(DATA_BITS-1 downto 0); + signal buff_reg, buff_next : std_logic; + signal max_tick : std_logic; + +begin + -- Drive inputs + in_next <= data_i; + + --registers + process (aclk) + begin + if rising_edge(aclk) then + if (aresetn = '0') then + cnt_reg <= (others => '0'); + in_reg <= (others => '0'); + out_reg <= (others => '0'); + r_reg <= (others => '0'); + buff_reg <= '0'; + else + cnt_reg <= cnt_next; + r_reg <= r_next; + buff_reg <= buff_next; + in_reg <= in_next; + out_reg <= out_next; + end if; + end if; + end process; + --next-state logic for counter + cnt_next <= (others => '0') when unsigned(cnt_reg) = (COUNT_MOD-1) else + std_logic_vector(unsigned(cnt_reg) + 1); + + buff_next <= '1' when (unsigned(r_reg) < unsigned(out_reg)) else '0'; + + r_next <= std_logic_vector(unsigned(r_reg) + 1); + + --output logic + max_tick <= '1' when unsigned(cnt_reg) = (COUNT_MOD-1) else '0'; + + process(max_tick, in_reg, out_reg) + begin + if (max_tick = '1') then + if (unsigned(in_reg) > unsigned(out_reg)) then + out_next <= std_logic_vector(unsigned(out_reg) + 1); + elsif (unsigned(in_reg) < unsigned(out_reg)) then + out_next <= std_logic_vector(unsigned(out_reg) - 1); + else + out_next <= out_reg; -- default + end if; + else + out_next <= out_reg; + end if; + end process; + + --next-state logic for output + data_o <= out_reg; + led_o <= '0' when (unsigned(out_reg) = 0) else + '1'; + pwm_o <= buff_reg; + +end rtl; diff --git a/cores/selector_v1_0/core_config.tcl b/cores/selector_v1_0/core_config.tcl new file mode 100644 index 0000000..9f9def7 --- /dev/null +++ b/cores/selector_v1_0/core_config.tcl @@ -0,0 +1,7 @@ +set display_name {Data Selector} + +set core [ipx::current_core] + +set_property DISPLAY_NAME $display_name $core +set_property DESCRIPTION $display_name $core + diff --git a/cores/selector_v1_0/selector.vhd b/cores/selector_v1_0/selector.vhd new file mode 100644 index 0000000..a57f516 --- /dev/null +++ b/cores/selector_v1_0/selector.vhd @@ -0,0 +1,27 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity selector is +generic ( + A_WIDTH : natural := 32; + DIV_WIDTH : natural := 5; + OFFSET : natural := 26; -- Slice bit position 26 ... 1.07 s + SCALE : integer := -1 +); +port ( + -- System signals + a : in std_logic_vector(A_WIDTH-1 downto 0); + div : in std_logic_vector(DIV_WIDTH-1 downto 0); + s : out std_logic +); +end selector; + +architecture rtl of selector is + +begin + + s <= a(OFFSET + SCALE*div); + +end rtl; -- GitLab