OpenCores
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;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.