URL
https://opencores.org/ocsvn/lateq/lateq/trunk
Subversion Repositories lateq
[/] [lateq/] [trunk/] [hdl_single_type/] [src/] [ex1_proc.vhd] - Rev 4
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------- -- Title : Example 1 - data processor -- Project : ------------------------------------------------------------------------------- -- File : ex1_proc.vhd -- Author : Wojciech M. Zabolotny <wzab01@gmail.com> -- Company : -- License : BSD -- Created : 2015-09-07 -- Last update: 2015-09-24 -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- -- Description: This file implements the data processor which demonstrates -- the methodology of automatic latency balancing in VHDL -- implemented pipelined blocks ------------------------------------------------------------------------------- -- Copyright (c) 2015 ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2015-09-07 1.0 wzab Created ------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; library work; use work.lateq_pkg.all; use work.ex1_pkg.all; use work.ex1_trees_pkg.all; entity ex1_proc is port ( din : in T_INPUT_DATA; -- data from the detector position : out T_USER_DATA; -- integral part of the hit position wgt_charge : out T_USER_DATA; -- weighted hit charge (for calculation -- of fractional part of position) charge : out T_USER_DATA; -- hit charge clk : in std_logic; -- system clock rst_p : in std_logic); -- reset end entity ex1_proc; architecture beh of ex1_proc is -- Input data in internal form signal din_int : T_USER_DATA_SET(0 to C_N_CHANNELS-1) := (others => C_USER_DATA_MRK_INIT); -- pragma translate_off -- Time marker signal s_lateq_mrk : T_LATEQ_MRK := C_LATEQ_MRK_INIT; -- pragma translate_on signal sel : integer; -- Maximum position converted to the common format signal dout_max : T_USER_DATA_MRK := C_USER_DATA_MRK_INIT; -- Input data with position of maximum - for first synchronizer signal din_and_pos_max_i, din_and_pos_max_o : T_USER_DATA_SET(0 to C_N_CHANNELS) := (others => C_USER_DATA_MRK_INIT); -- Selected data (around maximum) signal sel_data : T_USER_DATA_SET(0 to 2*C_N_SIDE_CHANS); -- Selected data multiplied by distance from maximum signal wgt_sel_data : T_USER_DATA_SET(0 to 2*C_N_SIDE_CHANS); -- results signal chrg_sum, wgt_chrg_sum : T_USER_DATA_MRK := C_USER_DATA_MRK_INIT; -- Results record (for second synchroniser) signal results_i, results_o : T_USER_DATA_SET(0 to 2); begin -- architecture beh -- Process which generates the time markers for the input data -- It is unclear. Should it be here, or in the testbench? pgm1 : process (clk) is begin -- process pgm1 if clk'event and clk = '1' then -- rising clock edge if rst_p = '1' then -- synchronous reset (active low) -- pragma translate_off s_lateq_mrk <= C_LATEQ_MRK_INIT; -- pragma translate_on din_int <= (others => C_USER_DATA_MRK_INIT); else for i in 0 to C_N_CHANNELS-1 loop din_int(i).data <= din(i); din_int(i).valid <= true; -- pragma translate_off din_int(i).lateq_mrk <= s_lateq_mrk; -- pragma translate_on end loop; -- i -- pragma translate_off s_lateq_mrk <= lateq_mrk_incr(s_lateq_mrk); -- pragma translate_on end if; end if; end process pgm1; -- The first block is the maximum finder. max_finder_1 : entity work.max_finder generic map ( N_OF_ALL_INS => C_N_CHANNELS ) port map ( dins => din_int, dout => dout_max, clk => clk, rst_p => rst_p); -- Now we should correct delays between the input data -- and output of the maximum finder -- So we have our delay adjustment block with two channels -- din_and_pos_max_i <= din_int & dout_max; ex1 : entity work.lateq generic map ( LEQ_ID => "LCEQ1", NCHANS => C_N_CHANNELS+1 ) port map ( din => din_and_pos_max_i, dout => din_and_pos_max_o, clk => clk, rst_p => rst_p); -- Now we can select channels surrounding the maximum data_sel_1 : entity work.data_sel generic map ( N_SIDE_CHANS => C_N_SIDE_CHANS) port map ( dins => din_and_pos_max_o(0 to C_N_CHANNELS-1), dout => sel_data, sel => din_and_pos_max_o(C_N_CHANNELS), clk => clk, rst_p => rst_p); -- Now for the selected channels we should calculate the charge and the -- weighted charge -- Generate the data multiplied by weigth (single clock delay) pws1 : process (clk) is begin -- process pws1 if clk'event and clk = '1' then -- rising clock edge if rst_p = '1' then -- synchronous reset (active high) wgt_sel_data <= (others => C_USER_DATA_MRK_INIT); else for i in 0 to 2*C_N_SIDE_CHANS loop wgt_sel_data(i) <= sel_data(i); -- Overwrite the data wgt_sel_data(i).data <= resize((i-C_N_SIDE_CHANS) * signed(sel_data(i).data), C_USER_DATA_WIDTH); end loop; -- i end if; end if; end process pws1; -- Here we calculate the sum of charge tree_adder_1 : entity work.tree_adder generic map ( N_OF_ALL_INS => 2*C_N_SIDE_CHANS+1 ) port map ( dins => sel_data, dout => chrg_sum, clk => clk, rst_p => rst_p); -- Here we calculate weighted sum of charge tree_adder_2 : entity work.tree_adder generic map ( N_OF_ALL_INS => 2*C_N_SIDE_CHANS+1 ) port map ( dins => wgt_sel_data, dout => wgt_chrg_sum, clk => clk, rst_p => rst_p); -- Now we have to equalize delays between the position, the sum -- of charge, and the weighted sum of charge results_i(0) <= din_and_pos_max_o(C_N_CHANNELS); results_i(1) <= chrg_sum; results_i(2) <= wgt_chrg_sum; ex2 : entity work.lateq generic map ( LEQ_ID => "LCEQ2", NCHANS => 3 ) port map ( din => results_i, dout => results_o, clk => clk, rst_p => rst_p); -- Now connect the output signals charge <= results_o(1).data; wgt_charge <= results_o(2).data; position <= results_o(0).data; end architecture beh;