URL
https://opencores.org/ocsvn/lateq/lateq/trunk
Subversion Repositories lateq
[/] [lateq/] [trunk/] [hdl_various_types/] [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_POS_INT; -- integral part of the hit position wgt_charge : out T_CALC_DATA; -- fractional part of the hit position charge : out T_CALC_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 signals in internal form (with time markers) signal din_int, din_int_a : T_INPUT_DATA_MRK := C_INPUT_DATA_MRK_INIT; -- pragma translate_off -- Time marker signal s_lateq_mrk : T_LATEQ_MRK := C_LATEQ_MRK_INIT; -- pragma translate_on -- Output signal from the max_finder signal dout_max : T_SINGLE_DATA_WITH_POS := C_SINGLE_DATA_WITH_POS_INIT; -- Selected data surrounding the maximum of the signal signal sel_data : T_SEL_DATA := C_SEL_DATA_INIT; -- Selected data with longer data word signal s_sel_data, wgt_sel_data : T_CALC_SEL_DATA := C_CALC_SEL_DATA_INIT; -- Sum of charge and weighted sum of charge signal chrg_sum, wgt_chrg_sum : T_CALC_DATA_MRK := C_CALC_DATA_MRK_INIT; -- Sum of charge and weighted sum of charge after synchronizer signal chrg_sum_b, wgt_chrg_sum_b : T_CALC_DATA_MRK := C_CALC_DATA_MRK_INIT; -- Position of maximum - delayed signals after other blocks or sycnhronizers signal s_position_a, s_position_b, s_position_c : T_POS_INT_MRK := C_POS_INT_MRK_INIT; 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 <= C_INPUT_DATA_MRK_INIT; else din_int.data_vec <= din; -- pragma translate_off din_int.lateq_mrk <= s_lateq_mrk; 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 -- s_position_a.position <= dout_max.position; -- pragma translate_off s_position_a.lateq_mrk <= dout_max.lateq_mrk; -- pragma translate_on ex1_eq_mf_1: entity work.ex1_eq_mf generic map ( LEQ_ID => "LCEQ1") port map ( in0 => din_int, out0 => din_int_a, in1 => s_position_a, out1 => s_position_b, 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_int_a, dout => sel_data, sel => s_position_b.position, 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 <= C_CALC_SEL_DATA_INIT; else for i in 0 to 2*C_N_SIDE_CHANS loop wgt_sel_data.data_vec(i) <= resize((i-C_N_SIDE_CHANS) * signed(sel_data.data_vec(i)),C_CALC_SUM_WIDTH); end loop; -- i -- pragma translate_off wgt_sel_data.lateq_mrk <= sel_data.lateq_mrk; -- pragma translate_on end if; end if; end process pws1; -- Map the selected data to the calc type (no delay) pws2: process(sel_data) is begin -- process pws2 for i in 0 to 2*C_N_SIDE_CHANS loop s_sel_data.data_vec(i) <= resize(signed(sel_data.data_vec(i)), C_CALC_SUM_WIDTH); end loop; -- i -- pragma translate_off s_sel_data.lateq_mrk <= sel_data.lateq_mrk; -- pragma translate_on end process pws2; -- 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 => s_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 ex1_eq_calc_1: entity work.ex1_eq_calc generic map ( LEQ_ID => "LCEQ2") port map ( in0 => s_position_b, out0 => s_position_c, in1 => chrg_sum, out1 => chrg_sum_b, in2 => wgt_chrg_sum, out2 => wgt_chrg_sum_b, clk => clk, rst_p => rst_p); -- Now connect the output signals charge <= chrg_sum_b.sum; wgt_charge <= wgt_chrg_sum_b.sum; position <= s_position_c.position; end architecture beh;