C . APPENDIX – C: VHDL CODE FOR THE MAIN DATA PATH AND DETAILED MEMORY MAP FOR THE DOWNLOADED PARAMETERS C .1: MAIN MEMORY DECODER ----------------------------------------------------------------------- -- This block decodes the main memory space ----------------------------------------------------------------------- -- The initialization of the standard library files ----------------------------------------------------------------------- --This revision 2B to modify the test lut data to 18 bits --Shweta Lolage: 10/05/2000 ----------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -----------------------------------------------------------------------entity main_memory_decoder is port (clock,reset: in std_logic; main_address:in std_logic_vector(14 downto 0); main_data_in: in std_logic_vector(31 downto 0); main_select,main_read,main_write: in std_logic; monitor_data_in,misc_parameters_data_in:in std_logic_vector(31 downto 0); gainoffset_data_in: in std_logic_vector(7 downto 0); roadlut_data_in : in std_logic_vector (21 downto 0); testlut_data_in: in std_logic_vector(17 downto 0); registered_data: out std_logic_vector(31 downto 0); registered_address: out std_logic_vector(14 downto 0); monitor_enable,misc_parameters_enable, gainoffset_enable,testlut_enable,roadlut_enable : out std_logic; global_write_not_read,global_dataoutput_enable: out std_logic; main_data_out: out std_logic_vector(31 downto 0) ); end entity main_memory_decoder; -------------------------------------------------------------------- --Architecture body architecture logic of main_memory_decoder is -- -- define memory map for address bits 14 downto 12 -- constant monitor_address_space:std_logic_vector(2 downto 0) := "0000"; constant misc_address_space: std_logic_vector(2 downto 0) := "0001"; constant gainoffset_address_space0: std_logic_vector(2 downto 0) := "0010"; constant gainoffset_address_space1: std_logic_vector(2 downto 0) := "0011"; constant gainoffset_address_space2: std_logic_vector(2 downto 0) := "0100"; constant gainoffset_address_space3: std_logic_vector(2 downto 0) := "0101"; constant test_address_space: std_logic_vector(2 downto 0) := "0110"; --- define constants for zero's to increase bit width of above memory space constant zero8: std_logic_vector(7 downto 0) := "00000000"; constant zero10: std_logic_vector(9 downto 0) := "0000000000"; constant zero14: std_logic_vector(13 downto 0) := "00000000000000"; constant zero15: std_logic_vector(14 downto 0) := "000000000000000"; constant zero24: std_logic_vector(23 downto 0) := "000000000000000000000000"; constant zero23: std_logic_vector(22 downto 0) := "00000000000000000000000"; constant zero32 : std_logic_vector(31 downto 0) := "00000000000000000000000000000000"; -- -- Define constants to determine if this is a read or write mode -- constant read_mode: std_logic := '0'; constant write_mode: std_logic := '1'; constant disabled: std_logic := '0'; constant enabled: std_logic := '1'; --- define signals to latch all external inputs signal nmain_address,pmain_address: std_logic_vector(14 downto 0); signal nmain_data_in,pmain_data_in: std_logic_vector(31 downto 0); signal nmain_read,pmain_read,nmain_write,pmain_write,nmain_select,pmain_select: std_logic; begin -- This process block sets the enables for each address space if this smt channel has been selected process(main_address,pmain_select) variable address: std_logic_vector(3 downto 0); variable vmonitor,vmisc,vgainoffset,vtestlut,vroadlut: std_logic; variable vdata_out: std_logic_vector(31 downto 0); variable memory_area_select : std_logic; -- this signal is to differentiate between the memory for memories on the chip -- and the road data memory outside the chips begin -- set default outputs vmonitor := '0'; vmisc := '0'; vgainoffset := '0'; vtestlut := '0'; vroadlut := '0'; vdata_out := zero32; address := main_address(12 downto 10); -- only need top 4 bits for address decoding -- Dr. Perry I have made this change according to the memory map we discussed memory_area_select := main_address(13); -- if select line was high during last cycle then immediately enable appropriate address space if(pmain_select = '1') then if (memory_area_select = '0') then case address is when monitor_address_space => vmonitor := '1'; vdata_out := monitor_data_in; when misc_address_space => vmisc := '1'; vdata_out := misc_parameters_data_in; when gainoffset_address_space0|gainoffset_address_space1 => vgainoffset := '1'; vdata_out := zero24&gainoffset_data_in; when gainoffset_address_space2|gainoffset_address_space3 => vgainoffset := '1'; vdata_out := zero24&gainoffset_data_in; when test_address_space => vtestlut := '1'; vdata_out := zero14&testlut_data_in; when others => null; end case; else vroadlut := '1'; vdata_out := zero10&roadlut_data_in; end if; end if; monitor_enable <= vmonitor; misc_parameters_enable <= vmisc; gainoffset_enable <= vgainoffset; testlut_enable <= vtestlut; roadlut_enable <= vroadlut; main_data_out <= vdata_out; end process; --- This process block is used to prepare data internally for read or write process(main_address,main_data_in,main_select,main_read,main_write, pmain_select,pmain_write) variable vaccess_mode,vgoe: std_logic; begin -- set default outputs nmain_address <= main_address; nmain_data_in <= main_data_in; nmain_select <= main_select; nmain_read <= main_read; nmain_write <= main_write; vaccess_mode := write_mode; -- default access mode to write mode vgoe := disabled; -- default global oe to disabled -- if not selected then we are in read mode -- if(pmain_select = '0') then vaccess_mode := read_mode; vgoe := disabled; --- we are not selected turn off global output enable elsif(pmain_write = '1') then vaccess_mode := write_mode; vgoe := disabled; -- we are selected but writing, turn off global output enable else vaccess_mode := read_mode; vgoe := enabled; -- we are selected and reading, turn on global output enable end if; global_dataoutput_enable <= vgoe; global_write_not_read <= vaccess_mode; end process; --- --- This is the register block --- process(clock,reset,nmain_select,nmain_address,nmain_data_in,nmain_read, nmain_write) begin if(reset = '0') then pmain_select <= '0'; pmain_address <= zero15; pmain_data_in <= zero32; pmain_read <= '0'; pmain_write <= '0'; elsif(clock='1' and clock'event) then pmain_select <= nmain_select; pmain_address <= nmain_address; pmain_data_in <= nmain_data_in; pmain_read <= nmain_read; pmain_write <= nmain_write; end if; end process; registered_data <= pmain_data_in; registered_address <= pmain_address; end architecture logic; C.2: MISCELLANEOUS MEMORY DECODER ------------------------------------------------------------------------------ -- This block decodes the misc memory space ------------------------------------------------------------------------------ -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity misc_memory_decoder is port (main_address:in std_logic_vector(10 downto 0); bad_channel_data,misc_parameters_data:in std_logic_vector(31 downto 0); chip_range_data,dedx_data: in std_logic_vector(23 downto 0); cluster_data:in std_logic_vector(16 downto 0); bad_channel_enable,chip_range_enable,dedx_enable,misc_parameters_enable, cluster_enable: out std_logic; misc_data_out: out std_logic_vector(31 downto 0) ); end entity misc_memory_decoder; -------------------------------------------------------------------- --Architecture body architecture logic of misc_memory_decoder is -- -- define memory map for address bits 11 downto 8 -- constant bad_channel_address_space:std_logic_vector(2 downto 0) := "000"; constant chip_range_address_space: std_logic_vector(2 downto 0) := "001"; constant dedx_address_space: std_logic_vector(2 downto 0) := "010"; constant misc_parameters_address_space: std_logic_vector(2 downto 0) := "011"; constant cluster_address_space: std_logic_vector(2 downto 0) := "100"; constant zero8: std_logic_vector(7 downto 0):= "00000000"; constant zero15: std_logic_vector(14 downto 0):= "000000000000000"; constant zero32 : std_logic_vector(31 downto 0):= "00000000000000000000000000000000"; begin -- This process block sets the enables for each address space process(main_address) variable address: std_logic_vector(2 downto 0); variable vbc,vcr,vdedx,vmp,vce: std_logic; begin -- set default outputs vbc := '0'; vcr := '0'; vdedx := '0'; vmp := '0'; vce := '0'; address := main_address(9 downto 7); -- only need top 3 bits for address decoding case address is when bad_channel_address_space => vbc := '1'; when chip_range_address_space => vcr := '1'; when dedx_address_space => vdedx := '1'; when misc_parameters_address_space => vmp := '1'; when cluster_address_space => vce := '1'; when others => null; end case; bad_channel_enable <= vbc; chip_range_enable <= vcr; dedx_enable <= vdedx; misc_parameters_enable <= vmp; cluster_enable <= vce; end process; --- use top three bits of address to mux correct data word out with main_address(10 downto 8) select misc_data_out <= bad_channel_data when "000", zero8&chip_range_data when "001", zero8&dedx_data when "010", misc_parameters_data when "011", zero15&cluster_data when "100", zero32 when others; end architecture logic; C.3: PULSE THRESHOLD CONTROL ------------------------------------------------------------------------------ -- This block decodes the memory addresses for the 8 de/dx parameters ------------------------------------------------------------------------------ -- Initial Design: Reginald Perry (07/23/2000) ------------------------------------------------------------------------------ -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity dedx_threshold_control is port (control_address: in std_logic_vector(5 downto 0); -- address from the control block logic_address : in std_logic_vector(1 downto 0); -- for chiprange design the logic address is always 0 write_enable, memory_enable : in std_logic; -- read request signal from the control block block0,block1,block2,block3: in std_logic_vector(23 downto 0); -- this is the block input data read_address : out std_logic_vector(5 downto 0); -- the mux control or logic read_address to the FIFO write_not_read0,write_not_read1,write_not_read2, write_not_read3 : out std_logic; block_out: out std_logic_vector(23 downto 0) -- this is the block data out ); end entity dedx_threshold_control; -------------------------------------------------------------------- --Architecture body architecture logic of dedx_threshold_control is signal control_memory_select: std_logic_vector(1 downto 0); begin -- let's use a with select to mux read address line -- use a separate mux for each memory block -- This is block 0 addresses 0-4 -- need two bits for address with memory_enable select --- use global_memory_enable to pick read_address read_address <= logic_address when '0', control_address(1 downto 0) when '1', logic_address when others; -- Define control memory select value control_memory_select <= control_address(3)&control_address(2); -- use a process block to determine write_not_read lines process(memory_enable,write_enable,control_memory_select,block0,block1,block2, block3) variable block_data : std_logic_vector(23 downto 0); variable write_access_required: std_logic; begin --- use another variable to decide if write access is required write_access_required := memory_enable and write_enable; if(write_access_required = '1') then --- need to determine which block wants access case control_memory_select is when "00" => write_not_read0 <='1'; write_not_read1 <='0'; write_not_read2 <='0'; write_not_read3 <='0'; when "01" => write_not_read0 <='0'; write_not_read1 <='1'; write_not_read2 <='0'; write_not_read3 <='0'; when "10" => write_not_read0 <='0'; write_not_read1 <='0'; write_not_read2 <='1'; write_not_read3 <='0'; when "11" => write_not_read0 <='0'; write_not_read1 <='0'; write_not_read2 <='0'; write_not_read3 <='1'; when others => -- should never come here write_not_read0 <='0'; write_not_read1 <='0'; write_not_read2 <='0'; write_not_read3 <='0'; end case; else -- this a read cyle, set all write_not_read lines low; write_not_read0 <='0'; write_not_read1 <='0'; write_not_read2 <='0'; write_not_read3 <='0'; end if; -- use another case statement as a mux to set block_data out case control_memory_select is when "00" => block_data := block0; when "01" => block_data := block1; when "10" => block_data := block2; when "11" => block_data := block3; when others => block_data := block0; end case; block_out <= block_data; end process; end architecture logic; C.4: PULSE MEMORY CONCATENATION ------------------------------------------------------------------------------ -- This block concatinates dedx values into one 36 bit word -- Include the possiblility for a three bit de/dx but don't do anything with those values now ------------------------------------------------------------------------------ -- Initial Design: Reginald Perry (07/03/2000) ------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity dedx_memory_concatination is port (block0,block1,block2,block3 : in std_logic_vector(23 downto 0); dedx_threshold_coarse: out std_logic_vector(35 downto 0); dedx_threshold_fine: out std_logic_vector(47 downto 0) ); end entity dedx_memory_concatination; -------------------------------------------------------------------- --Architecture body -- memory map -- dedx_threshold_coarse has coarse level approximations (2 bits) -- dedx_threshold_fine gives one additional bit between coarse levels -- Example: note high is (23 downto 12) while low is (11 downto 0) -- coarse fine -- max FFF -- block3_high -- block1_low -- block3_low -- block0_high -- block2_high -- block0_low -- block2_low -- min 000 architecture logic of dedx_memory_concatination is begin dedx_threshold_coarse(35 downto 24) <= block1(11 downto 0); dedx_threshold_coarse(23 downto 0) <= block0; dedx_threshold_fine <= block3&block2; end architecture logic; C.5: CLUSTER THRESHOLD CONTROL ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (07/03/2000) ------------------------------------------------------------------------------ -- -- Modified 7/20/2000 Simplify logic RJP -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity cluster_threshold_control is port (control_address: in unsigned(1 downto 0); -- address from the control block logic_address : in unsigned(1 downto 0); -- for chiprange design the logic address is always 0 write_enable, memory_enable : in std_logic; -- read request signal from the control block read_address : out unsigned(1 downto 0); -- the mux output read_address to the FIFO write_not_read : out std_logic ); end entity cluster_threshold_control; -------------------------------------------------------------------- --Architecture body architecture logic of cluster_threshold_control is begin -- let's use a with select to mux read address line -- we only have 3 types so set top three bits of address space equal to zero with memory_enable select --- use test_enable to pick read_address read_address <= logic_address when '0', control_address when '1', logic_address when others; -- use simple data_path statement for write_not_read --- write_not_read is write_enable and test_enable write_not_read <= memory_enable and write_enable; end architecture logic; C.6: CHIP RANGE CONTROL ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (07/03/2000) ------------------------------------------------------------------------------ -- -- Modified 7/20/2000 Simplify logic RJP -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity chiprange_control is port (control_address: in unsigned(5 downto 0); -- address from the control block write_enable, memory_enable : in std_logic; -- read request signal from the control block read_address : out unsigned(1 downto 0); -- the mux output read_address to the FIFO write_not_read : out std_logic ); end entity chiprange_control; -------------------------------------------------------------------- --Architecture body architecture logic of chiprange_control is constant logic_address: unsigned(5 downto 0) := "000000"; begin -- let's use a with select to mux read address line with memory_enable select --- use test_enable to pick read_address read_address <= logic_address(1 downto 0) when '0', control_address(1 downto 0) when '1', logic_address(1 downto 0) when others; -- use simple data_path statement for write_not_read --- write_not_read is write_enable and test_enable write_not_read <= memory_enable and write_enable; end architecture logic; C.7: MISCELLANEOUS DOWNLOADED PARAMETER SPLITTER ------------------------------------------------------------------------------ -- This block splits the 32 bit long misc downloaded parameter word into -- individual blocks ------------------------------------------------------------------------------ -- Initial Design: Reginald Perry (07/03/2000) ------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity misc_downloaded_parameter_splitter is port (data_in : in std_logic_vector(31 downto 0); dp_test_bit,dp_disable_bit: out std_logic; dp_smt_id: out std_logic_vector(2 downto 0); dp_delay_count,dp_seq_id: out std_logic_vector(7 downto 0); dp_hdi_id: out std_logic_vector(2 downto 0) ); end entity misc_downloaded_parameter_splitter; -------------------------------------------------------------------- --Architecture body architecture logic of misc_downloaded_parameter_splitter is begin dp_test_bit <= data_in(28); dp_disable_bit <= data_in(27); dp_smt_id <= data_in(26 downto 24); dp_delay_count <= data_in(23 downto 16); dp_seq_id <= data_in(15 downto 8); dp_hdi_id <= data_in(2 downto 0); end architecture logic; C.8: TEST DATA CONTROL ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (07/03/2000) ------------------------------------------------------------------------------ -- -- Modified 7/20/2000 Simplify logic RJP -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity testdata_control is port (control_address: in unsigned(7 downto 0); -- address from the control block logic_address : in unsigned(7 downto 0); -- address form the logic for the bad channels write_enable, test_enable : in std_logic; -- read request signal from the control block read_address : out unsigned(7 downto 0); -- the mux output read_address to the FIFO write_not_read : out std_logic ); end entity testdata_control; -------------------------------------------------------------------- --Architecture body architecture logic of testdata_control is constant zero11 : unsigned (10 downto 0):= "00000000000"; begin -- let's use a with select to mux read address line with test_enable select --- use test_enable to pick read_address read_address <= logic_address when '0', control_address when '1', logic_address when others; -- use simple data_path statement for write_not_read --- write_not_read is write_enable and test_enable write_not_read <= test_enable and write_enable; end architecture logic; C.9: BAD CHANNEL CONTROL ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (07/03/2000) ------------------------------------------------------------------------------ -- Modified 7/20/2000 Simplify logic RJP -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity badchannel_control is port (control_address: in unsigned(10 downto 0); -- address from the control block logic_address : in unsigned(10 downto 0); -- address form the logic for the bad channels write_enable, memory_enable : in std_logic; -- read request signal from the control block read_address : out unsigned(10 downto 0); -- the mux output read_address to the FIFO write_not_read : out std_logic ); end entity badchannel_control; -------------------------------------------------------------------- --Architecture body architecture logic of badchannel_control is begin -- let's use a with select to mux read address line with memory_enable select --- use test_enable to pick read_address read_address <= logic_address when '0', control_address when '1', logic_address when others; -- use simple data_path statement for write_not_read --- write_not_read is write_enable and test_enable write_not_read <= memory_enable and write_enable; end architecture logic; C.10: BAD CHANNEL MULTIPLEXER ------------------------------------------------------------------------------ -- Version 1 This code decodes the data for the bad channels as the data -- from the control is down loaded in set of 32 words, with each word representing -- the status of 32 channels. This logic finds out the individual channel status. ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (6/27/2000) -- Simplify Logic: RJP (7/21/2000) ------------------------------------------------------------------------------ -- Initializations to the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity bad_channel_mux is port (data_word : in unsigned (31 downto 0); address : in integer range 31 downto 0; bad_channel_status : out std_logic ); end entity bad_channel_mux; ---------------------------------------------------------------------------------- --Architectural body of the design architecture logic of bad_channel_mux is begin -- use with select to mux with address select bad_channel_status <= data_word(0) when 0, data_word(1) when 1, data_word(2) when 2, data_word(3) when 3, data_word(4) when 4, data_word(5) when 5, data_word(6) when 6, data_word(7) when 7, data_word(8) when 8, data_word(9) when 9, data_word(10) when 10, data_word(11) when 11, data_word(12) when 12, data_word(13) when 13, data_word(14) when 14, data_word(15) when 15, data_word(16) when 16, data_word(17) when 17, data_word(18) when 18, data_word(19) when 19, data_word(20) when 20, data_word(21) when 21, data_word(22) when 22, data_word(23) when 23, data_word(24) when 24, data_word(25) when 25, data_word(26) when 26, data_word(27) when 27, data_word(28) when 28, data_word(29) when 29, data_word(30) when 30, data_word(31) when 31, data_word(0) when others; end architecture logic; C.11: GAIN OFFSET CONTROL ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (07/03/2000) ------------------------------------------------------------------------------ -- -- Modified 7/20/2000 Simplify logic RJP -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity gainoffset_control is port (control_address: in unsigned(11 downto 0); -- address from the control block logic_address : in unsigned(11 downto 0); -- address form the logic for the bad channels write_enable, memory_enable : in std_logic; -- read request signal from the control block read_address : out unsigned(11 downto 0); -- the mux output read_address to the FIFO write_not_read : out std_logic ); end entity gainoffset_control; -------------------------------------------------------------------- --Architecture body architecture logic of gainoffset_control is begin -- let's use a with select to mux read address line with memory_enable select --- use test_enable to pick read_address read_address <= logic_address when '0', control_address when '1', logic_address when others; -- use simple data_path statement for write_not_read --- write_not_read is write_enable and test_enable write_not_read <= memory_enable and write_enable; end architecture logic; C.11: SMT DATA FILTER ----------------------------------------------------------------------------- -- Revision 2.1 SMT Data Filter -- Based on 5/26/2000 Document -- Earle, Specifications for One Channel of the STC Logic ----------------------------------------------------------------------------- -- Initial Design: Reginald J. Perry (6/4/2000) ----------------------------------------------------------------------------- -- Modified 6/22/00 based on new specs: Reginald J. Perry -- Add 18 bit output (double byte wide) -- Modified 7/14/00 RJP -- Add delay counter for event number -- Modified 8/02/00 Shweta Lolage -- to change the format of the smt_out to fit the specifications -- and minor changes to filter the excess C0's -- Modified 10/05/00 Shweta Lolage -- to remove the test inputs as they will be mux-ed with the FIFO output -- to go directly to the Strip reader control --------------------------------------------------------------------------- -- This block filters raw SMT data before it is stored in the input FIFO -- Complex delay counter currently does not fit. Implement simple delay counter for now -- -- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; --------------------------------------------------------------------------- entity smt_data_filter is port (delay_in: in unsigned(7 downto 0); -- this is the delay in FRC start signal frc_start: in std_logic; -- this indicates that FRC data has arrived disable: in std_logic; --- this bit is used to turn off the channel event_in: in unsigned(7 downto 0); -- this is the event number reset,clock,cav,dav,lnkrdy,smt_error_in: in std_logic; smt_in: in unsigned(7 downto 0); end_of_event: out std_logic; -- specifies the end of event smt_out: out unsigned(17 downto 0); wrreq: out std_logic ); end entity smt_data_filter; ----------------------------Architecture --------------------------- architecture logic_design of smt_data_filter is ---------------------Signal and constant Declaration-------------------------- signal delay_eq_zero,tdelay: std_logic; signal nserr,pserr: std_logic; -- this bit is used to record the serr signal nsmt_out,psmt_out: unsigned(17 downto 0); -- this register is used to hold smt data signal ndelay,pdelay: unsigned(7 downto 0); -- this is the internal delay counter constant zero18: unsigned(17 downto 0) := "000000000000000000"; constant zero8: unsigned(7 downto 0) := "00000000"; constant zero_address: unsigned(7 downto 0) := "00000000"; constant zC0: unsigned(7 downto 0) := "11000000"; type mystates is (s0,s1,s2,s3,s4); signal ns,ps,ndcs,pdcs: mystates; begin -- need two states to write data process(ps, psmt_out,smt_error_in,cav,dav,lnkrdy,event_in,pdelay,pserr) variable vsmt_enabled: std_logic; variable vsmt_in,vupper,vlower: unsigned(7 downto 0); begin -- set default outputs ns <= ps; nserr <= pserr; end_of_event <= '0'; nsmt_out <= psmt_out; vupper := psmt_out(15 downto 8); -- this is the last data byte vsmt_in := smt_in; -- use variable to hold the input stream data. -- this is the real data --- SMT data is valid if --- dav = lnkrdy=0 and cav=1 and enable = 1 and disable = 0 --- use a simple logic expression for this. Save in a variable vsmt_enabled := (not dav) and (not lnkrdy) and cav and (not disable); -- if channel is active then access the state machine if (vsmt_enabled= '1') then case ps is when s0 => --- this state is also used to initialize the delay counter. See process delay_counter end_of_event <= '0'; wrreq <= '0'; nsmt_out(17) <= smt_error_in; nsmt_out(15 downto 8) <= vsmt_in; -- this reads the upper byte of the word -- -- we were told that you can't start up with C0s. -- So no need to filter them here -- go immediately to s1 -- ns <= s1; when s1 => -- this is the lower byte -- If upper byte is C0 then go to s2 to wait for delay counter to be zero to write event number -- into trailer end_of_event <= '0'; if(vupper = zC0) then ns <= s2; wrreq <= '0'; else -- we have not seen trailer C0 in upper byte, use smt_in for lower byte. wrreq <= '0'; --- we will enable output FIFO in next state --- use this state to load register vlower := vsmt_in; end_of_event <= '0'; -- we are not at end of event ns <= s3; -- use s3 to write current word to FIFO and read next upper byte nsmt_out(7 downto 0) <= vlower; nsmt_out(16) <= smt_error_in; end if; -- this is the end of the current channel, -- must wait for delay_eq_zero to assert before writing trailer when s2 => end_of_event <= '0'; wrreq <= '0'; --- need to wait in here for delay to go to zero nsmt_out <= '1'&pserr&zC0&event_in; -- need to use dummy state to actually write FIFO. See s3 below if(delay_eq_zero = '1') then -- write out the trailer if delay is zero -- for the trailer, use msb for eof and use the next bit for serr ns <= s4; -- go back to s0 and start over else ns <= s2; end if; when s3 => -- use this state to write last word and read next upper byte -- for non end of event end_of_event <= '0'; -- set serr based on two error bits and current value of serr. ---- Use boolean equation nserr <= psmt_out(17) or psmt_out(8) or pserr; wrreq <= '1'; -- wrreq is not latched so it goes high immediately when we enter -- s3. Data word will be latched on the next clock edge. Timing -- is a bit problematic here because new -- dataword is being written at the same time. Therefore, -- -- output FIFO must latch on -- rising edge of clock when wrreq is enabled. nsmt_out(17) <= smt_error_in; nsmt_out(15 downto 8) <= vsmt_in; -- this reads the next upper byte of the word ns <= s1; -- go to s1 to see if this is a C0 when s4 => -- this is the write for an end of event end_of_event <= '1'; wrreq <= '1'; if( vsmt_in = zC0) then -- if the next byte after the end of event is still C0 then wait in this state -- till you get anything other than C0. ns <= s4; else ns <= s0; -- go to s0 to reset delay counter end if; when others => -- should never come here ns <= s0; end case; else -- if channel goes off or we are disabled, reset to s0 wrreq <= '0'; end_of_event <= '0'; ns <= s0; end if; end process; -- This process block implements the simple "delay" counter. Not exactly sure what it is used for RJP delay_counter: process(pdelay, ps, delay_in,frc_start,pdcs) variable temp_delay: std_logic; variable i: integer; begin ndelay <= pdelay; ndcs <= pdcs; -- use a variable to determine if current count is zero temp_delay := '0'; for i in 7 downto 0 loop temp_delay := temp_delay or pdelay(i); -- OR all bits to determine if we are at zero end loop; tdelay <= temp_delay; -- this is the main state machine for delay counter case pdcs is when s0 => --- we are waiting to start the counter in this state delay_eq_zero <= '0'; ndelay <= delay_in; ndcs <= s0; -- come back here if channel is inactive if(ps=s1) then ndcs <= s1; -- smt data has started counter end if; if(frc_start = '1') then ndcs <= s4; --- frc_start has started counter end if; -- For simple delay counter, we will only have three states. when s1 => delay_eq_zero <= '0'; if(tdelay = '0') then ndcs <= s3; -- go to s3 to set delay_eq_zero = 1 else ndelay <= pdelay - 1; -- decrement ndelay ndcs <= s1; -- come back to this state end if; if(frc_start = '1') then --- should be able to combine with above but synth tool choked on this ndcs <= s3; end if; -- in this state we set delay_eq_zero = 1 and hold it until main FSM resets by -- going back to s0 when s3 => delay_eq_zero <= '1'; -- check if main FSM is in s0, if so reset this FSM to S0 otherwise stay here if(ps = s0) then ndcs <= s0; else ndcs <= s3; end if; -- -- use smt data to stop counter -- when s4 => delay_eq_zero <= '0'; if(tdelay = '0') then ndcs <= s3; -- go to s3 to set delay_eq_zero = 1 else ndelay <= pdelay - 1; -- decrement ndelay ndcs <= s4; -- come back to this state end if; if(ps=s1) then --- should be able to combine with above but synth tool choked on this ndcs <= s3; end if; when others => -- should never come here ndcs <= s0; delay_eq_zero <= '0'; end case; end process; -- register block reg: process(ns,ndcs,nsmt_out,clock,reset,ndelay,nserr) begin if(reset = '0') then ps <= s0; pdcs <= s0; psmt_out <= zero18; pdelay <= zero8; pserr <= '0'; elsif (clock'event and clock='1') then ps <= ns; pdcs <= ndcs; psmt_out <= nsmt_out; pdelay <= ndelay; pserr <= nserr; end if; end process reg; smt_out <= psmt_out; -- this goes to the output fifo end architecture logic_design; --End of architecture block C.12: SMT TEST SELECT ------------------------------------------------------------------------------ -- Version 0 This block is used to decide between the read address from the -- control module or from the logic ------------------------------------------------------------------------------ -- Initial Design: Shweta Lolage (10/05/2000) ------------------------------------------------------------------------------ -- The initialization of the standard library files ------------------------------------------------------------------------------ library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ------------------------------------------------------------------------------- entity smt_test_select is port (clock,reset : in std_logic; test_data, fifo_data : in unsigned (17 downto 0); l3_raw_data_eof : in std_logic; -- this signal is taken from the strip reader control event_start, test , read_data: in std_logic; -- event start is the main signal which indicates start of an -- -- event for the channel -- test input this indicates whether the strip reader is going to -- process real data -- or this event is a test run -- read data is the signal from the strip reader -- to read the next 18 bit word fifo_empty : in std_logic; -- signal from the smt fifo; logic_address : out unsigned(7 downto 0); -- for test lut strip_reader_data : out unsigned (17 downto 0); read_fifo, memory_fifo_empty : out std_logic -- read_req signal to the FIFO -- fifo or memory empty signal for strip reader ); end entity smt_test_select; -------------------------------------------------------------------- --Architecture body architecture logic of smt_test_select is type mystates is (stest,sstart,sfirst,saddress); signal ps, ns : mystates; signal naddress, paddress : unsigned (7 downto 0); signal read_test : std_logic; -- signal indicating to increment the address for next word signal int_test : std_logic; -- this signal is used to latch the test signa -- I am not sure whether this signal -- will remain high all the time test data is running -- or will be a pulse indicating test mode signal test_lut_empty : std_logic; constant zero8 : unsigned(7 downto 0) := "00000000"; constant zero18 : unsigned (17 downto 0) := "000000000000000000"; constant max_count : unsigned (7 downto 0) := "11111111"; begin main: process (ps,test,event_start,paddress) begin naddress <= paddress; case ps is when stest => int_test <= '0'; -- check for the test input to go to the next state if (test = '1') then int_test <= '1'; ns <= sstart; else int_test <= '0'; ns <= stest; end if; when sstart => -- initialize the adddress and the testlut empty signal naddress <= zero8; test_lut_empty <= '0'; if(event_start = '1') then ns <= sfirst; else ns <= sstart; end if; when sfirst => -- this the word read out of the test lut if(read_test = '1') then naddress <= zero8; -- this just to make sure that the first word is read out ns <= saddress; else ns <= sfirst; end if; when saddress => -- the machine will remain in this state till the reset signal comes in if(read_test = '1') then naddress <= paddress + 1; else naddress <= paddress; end if; if (l3_raw_data_eof = '0') then ns <= saddress; else ns <= stest; end if; when others => ns <= stest; end case; end process main; process(int_test,read_data) variable vread_test, vread_fifo : std_logic; begin if (ps = sfirst or ps = saddress) then vread_test := read_data; vread_fifo := '0'; else vread_test:= '0'; vread_fifo:= read_data; end if; read_test <= vread_test; read_fifo <= vread_fifo; end process; reg: process (clock,reset,ps, paddress) begin if (reset = '0') then ps <= stest; paddress <= zero8; elsif( clock'event and clock ='1') then ps <= ns; paddress <= naddress; end if; end process; -- with select to mux read data with int_test select --- use test_enable to pick read_address strip_reader_data <= fifo_data when '0', test_data when '1', zero18 when others; with int_test select --- use test_enable to pick read_address memory_fifo_empty <= fifo_empty when '0', test_lut_empty when '1', -- this just a dummy signal '0' when others; logic_address <= paddress; end architecture logic; C.13: STRIP READER CONTROL ----------------------------------------------------------------------------- -- Revision 2.1 Strip Reader Control -- Based on 6-22-00 Document ----------------------------------------------------------------------------- -- Modified by Shweta Lolage(04-10-2000) -- Modified by Reginald Perry (6-4-2000) -- Add comments and fix up notation -- Add some monitoring counters -- Modified by Reginald Perry (6-5-2000) -- Add additional monitoring counters -- Modified by Reginald Perry (6-22-2000) -- Add 18 bit SMT input -- Modified by Reginald Perry (7-12-2000) -- Add monitor clear input -- Add chip monitor counters --- Modified by RJP (7/21/2000) -- Need to add rawdata l3 output -- Modified to add the initial state by Shweta Lolage (09-07-2000) ----------------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; library cluster_package; use cluster_package.cluster_package.all; ----------------------------------------------------------------------------- -- This block defines the inputs and outputs of the counter - ----------------------------------------------------------------------------- entity strip_reader_control is port(reset,clock,input_fifo_empty,output_fifo_full,monitor_clear, event_start : in std_logic; smt_in: in unsigned(2 downto 0); bad_channel_data :in std_logic; -- bad channel data is read from a rom stream_in: in unsigned(17 downto 0); -- MSB of stream_in is Error bit from SMT channel seqid: in unsigned(7 downto 0); hdiid: in unsigned(2 downto 0); corrected_data:in unsigned (7 downto 0); --- this is input data_type parameteric data in the format --- of axial, stereo, and ninety_degrees --- (low followed by high) data_range_in: in unsigned(23 downto 0);-- start of output data oread,owrite:out std_logic; -- signals used to enable input and output fifo ostate :out unsigned(3 downto 0); bad_channel_address:out unsigned(10 downto 0); chip_data : out unsigned (11 downto 0); output:out unsigned (22 downto 0); -- monitoring data l3_correcteddata: out unsigned(24 downto 0); -- note l3_out(22) is the end of event bit chip_monitor: out chip_array; smt_monitor: out smt_array; l3_rawdata: out unsigned(17 downto 0); l3_rawdata_eof,l3_rawdata_enable: out std_logic ); end entity strip_reader_control; ----------------------------Architecture Begining--------------------------- architecture logic_design of strip_reader_control is ---------------------Signal and constant Declaration-------------------------- signal neof,peof,nmismatchbit,pmismatchbit,pbc,nbc,nserr,pserr: std_logic; signal pnew_event,nnew_event: std_logic; signal n_new_data_flag,p_new_data_flag: std_logic; signal nseq_id,pseq_id: unsigned(7 downto 0); signal nhdi_id,phdi_id: unsigned(2 downto 0); signal noutput,poutput : unsigned (22 downto 0); signal nchip_id,pchip_id : unsigned (3 downto 0); signal nchan_id,pchan_id : unsigned (6 downto 0) ; signal ndata_type, pdata_type: unsigned(1 downto 0); signal nstate, pstate : unsigned(3 downto 0); signal nbad_channel_address, pbad_channel_address: unsigned(10 downto 0); signal nchip_data,pchip_data : unsigned (11 downto 0); ----- --- These signals are for monitoring information --- signal nsmt_mismatch_count,psmt_mismatch_count,nsmt_error_count, psmt_error_count: unsigned(23 downto 0); signal nsmt_zero_error,psmt_zero_error,nl3_trailer, pl3_trailer: unsigned(23 downto 0); -- These signals are used in the clear operation for the monitor counters. signal nchip,pchip: chip_array; -- chip array is defined in cluster_package constant zero9 : unsigned (8 downto 0) := "000000000"; constant zero8 : unsigned (7 downto 0) := "00000000"; constant zero7 : unsigned (6 downto 0) := "0000000"; constant zero4 : unsigned (3 downto 0) := "0000"; constant zero3 : unsigned (2 downto 0) := "000"; constant C0 : unsigned (7 downto 0) := "11000000"; constant zero2 : unsigned (1 downto 0) := "00"; constant initial_state : unsigned (3 downto 0):= "0000"; constant first_read_state : unsigned (3 downto 0):= "0001"; constant seq_hdi_state : unsigned (3 downto 0):= "0010"; constant chip_zero_state : unsigned (3 downto 0):= "0011";-- State constants constant chan_value_state : unsigned (3 downto 0):= "0100"; constant wait_for_data_state : unsigned (3 downto 0):= "0101"; constant correctvalue_state : unsigned (3 downto 0):= "0110"; constant write_fifo_state : unsigned (3 downto 0):= "0111"; constant read_fifo_state : unsigned (3 downto 0):= "1000"; constant read_wait_state : unsigned (3 downto 0):= "1001"; constant zero23 : unsigned (22 downto 0) := "00000000000000000000000"; constant zero24 : unsigned (23 downto 0) := "000000000000000000000000"; constant high : std_logic := '1'; constant low : std_logic := '0'; -- constant constant chip0 : unsigned(3 downto 0) := "0000"; constant chip1 : unsigned(3 downto 0) := "0001"; constant chip2 : unsigned(3 downto 0) := "0010"; constant chip3 : unsigned(3 downto 0) := "0011"; constant chip4 : unsigned(3 downto 0) := "0100"; constant chip5 : unsigned(3 downto 0) := "0101"; constant chip6 : unsigned(3 downto 0) := "0110"; constant chip7 : unsigned(3 downto 0) := "0111"; constant chip8 : unsigned(3 downto 0) := "1000"; constant chip9 : unsigned(3 downto 0) := "1001"; -- valid data types are now defined in cluster package --constant undefined_type: unsigned(1 downto 0) := "00"; --constant stereo_type : unsigned(1 downto 0) := "01"; --constant axial_type: unsigned(1 downto 0) := "10"; --constant ninety_degrees_type: unsigned(1 downto 0) := "11"; -- to define the states of the decoder -- type mystates is (sinit,sfirst_word,seq_hdi,chip_zero,chan_value,wait_for_data,fill_output_fifo, write_fifo,read_fifo,read_wait); signal ns,ps,nrs,prs : mystates; type event_states is (sinit,snew_event,swait1,swait2,sevent); signal nevent_state,pevent_state: event_states; -----------------------------Block Begins----------------- begin process(pstate,ps,prs,poutput,pchip_id,pchan_id,p_new_data_flag,pdata_type, corrected_data,peof,pseq_id,phdi_id,bad_channel_data,seqid,hdiid, input_fifo_empty,psmt_mismatch_count,psmt_zero_error,pmismatchbit, output_fifo_full,pchip,monitor_clear,pbc,pserr,pnew_event) --- Variable declaration --- --- Use variables to much of the state information. Need to include a definition table (RJP 6/4/00) variable voutput : unsigned ( 22 downto 0); variable vnew_data_flag,vend_of_event: std_logic; variable verror_high,verror_low: unsigned(0 downto 0); variable vchip_id : unsigned(3 downto 0); variable vchan_id: unsigned(6 downto 0); variable vstream_high_byte,vstream_low_byte,vseq_id: unsigned(7 downto 0); variable vhdi_id: unsigned(2 downto 0); variable vdata_type:unsigned(1 downto 0); variable next_state,return_state: mystates; variable vstate : unsigned(3 downto 0); variable veof,vbc,vserr: std_logic; begin -- -- Default Outputs -- -- -- Default variable values -- vstate := pstate; vnew_data_flag := p_new_data_flag; next_state := ps; voutput := poutput; veof := peof; vdata_type := pdata_type; vchip_id := pchip_id; vchan_id := pchan_id; vseq_id := pseq_id; vhdi_id := phdi_id; vbc := pbc; vserr := pserr; verror_high(0) := stream_in(17); verror_low(0) := stream_in(16); vstream_high_byte := stream_in(15 downto 8); -- MSB of stream data vstream_low_byte := stream_in(7 downto 0); -- LSB of stream data return_state := prs; nchip_data <= pchip_data; --- smt counters nsmt_mismatch_count <= psmt_mismatch_count; nsmt_zero_error <= psmt_zero_error; nmismatchbit <= pmismatchbit; nbad_channel_address <= pchip_id&pchan_id; -- this is used to address bad channel prom -- -- Chip counters -- default outputs -- nchip <= pchip; -- -- Check for serr -- vserr := verror_high(0) or verror_low(0) or pserr; -- set l3_rawdata to defaults. l3_rawdata <= stream_in; l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; --------------------- ----CASE STATEMENT -- --------------------- -- The following case statment will look at the incoming stream of data and --will proceed to -- compare and check for the validity of the same. For each case different actions will occur. -- Note1: Every state requires to have a read fifo before it can proceed to check the information. -- Note2: After the channel state and 11-bit word composed of the chip and channel id are sent to -- to an lpm rom, which will send an 9 bit word back into the decoder. From this 9 bit word we -- will look at the MSB and if it is "0" then we know that the channel is ok. -- Note3: Only the channel and Value state will have the command to enable writing to the FIFO. CASE ps IS -- the initial state in which the FSM is waiting for the event start When sinit => vstate := initial_state; if (event_start = '1') then next_state := sfirst_word; else next_state := sinit; end if; -- the initial state in which the first word is read outof the fifo when sfirst_word => vstate := first_read_state; if (pevent_state = sevent) then next_state := read_fifo; return_state := seq_hdi; else next_state := sfirst_word; end if; -- Sequence State -- Check for correct sequence ID and hdi_id -- WHEN seq_hdi => vstate := seq_hdi_state; -- variable used to check current state this is for debugging only next_state := read_fifo; return_state := chip_zero; vnew_data_flag := high; -- set new data high when looking for seqid and hdiid vseq_id := vstream_high_byte; -- save the sequence id vhdi_id := vstream_low_byte(2 downto 0); --- save the hdi id. It is bits 2,1,0 nmismatchbit <= low; -- reset mismatch bit if((vstream_high_byte /= seqid) or (vstream_low_byte /= hdiid)) then --when stream does not equal the preset value -- need to count the number of errors in seq_Id mismatch nsmt_mismatch_count <= psmt_mismatch_count + 1; nmismatchbit <= high; -- set the mismatch bit high end if; -- need to enable l3_rawdata so that l3 will latch when we change states l3_rawdata_eof <= '0'; l3_rawdata_enable <= '1'; -- CHIP State -- Check for correct chip ID and zero_byte WHEN chip_zero => vstate := chip_zero_state; next_state := read_fifo; if(vstream_low_byte /= zero7) then -- check that low byte is zero nsmt_zero_error <= psmt_zero_error + 1; end if; if (vstream_high_byte(7) = high) then --- if MSB = 1 this is a new chip. Save chip ID vchip_id := vstream_high_byte(3 downto 0); -- and return to channel value return_state := chan_value; else return_state := chip_zero; --- If MSB is not 1 then error come back to this state end if; --- and look for valid chip id -- need to save l3 raw l3_rawdata_eof <= '0'; l3_rawdata_enable <= '1'; -- CHANNEL State -- -- Get Channel ID and Value from Stream WHEN chan_value => -- The channel ID is read from stream vstate := chan_value_state; -- next_state := read_fifo; return_state := chan_value; veof := '0'; if (vstream_high_byte = C0) then -- if channel is C0 then we are at the end of event veof := high; -- event number is in low_byte so save it in voutput voutput(18 downto 11) := vstream_low_byte; next_state := fill_output_fifo; -- jump to fill_output_fifo return_state := sinit; -- return to next sequence ID after write fifo l3_rawdata_enable <= '1'; l3_rawdata_eof <= '1'; -- set end of event bit elsif (vstream_high_byte(7) = '1') then -- This means this is a new chip ID next_state := chip_zero; -- Check for a new type of chip. Do NOT read fifo. l3_rawdata_enable <= '0'; -- do not write into l3 l3_rawdata_eof <= '0'; else next_state := wait_for_data; -- this is a regular channel/data pair vchan_id := vstream_high_byte(6 downto 0); -- need to goto a wait state to give LUT enough nchip_data <= pchip_id&vstream_low_byte; -- time to access corrected data l3_rawdata_eof <= '0'; l3_rawdata_enable <= '1'; -- enable l3 rawdata end if; -- come back here after write -- wait for data State -- -- This is a dummy state to wait for the corrected data to come from the LUT. WHEN wait_for_data => vstate := wait_for_data_state; next_state := fill_output_fifo; -- go to fill output fifo state --- --- Data is valid, Increment chip monitor counters here -- -- Chip counters -- default outputs -- nchip <= pchip; case vchip_id is when chip0 => nchip(0) <= add_one(pchip(0)); when chip1 => nchip(1) <= add_one(pchip(1)); when chip2 => nchip(2) <= add_one(pchip(2)); when chip3 => nchip(3) <= add_one(pchip(3)); when chip4 => nchip(4) <= add_one(pchip(4)); when chip5 => nchip(5) <= add_one(pchip(5)); when chip6 => nchip(6) <= add_one(pchip(6)); when chip7 => nchip(7) <= add_one(pchip(7)); when chip8 => nchip(8) <= add_one(pchip(8)); when others => nchip <= pchip; --- should never come here; end case; -- DO NOT enable l3 raw here l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; WHEN fill_output_fifo => vstate := correctvalue_state; -- This is a bit backward but if veof leave voutput(18 downto 11) only. This was set in chan_value state -- if not end of event that check for a bad channel and replace with zero if true -- otherwise use corrected data in output. Hopefully, the synthesis tool can clean this up if(peof = '1') then voutput(18 downto 11) := voutput(18 downto 11); -- if at end of event, leave voutput only but reset vserr; elsif(bad_channel_data = '1') then -- bad channel LUT is access using pchip_id and pchannel_id voutput(18 downto 11) := zero8; -- this channel is bad, replace data with zero else voutput(18 downto 11) := corrected_data; -- not eof and channel good, replace with end if; -- corrected data voutput(22 downto 21) := pdata_type; voutput(20) := p_new_data_flag; voutput(19) := peof; voutput(10 downto 7) := pchip_id; voutput(6 downto 0) := pchan_id; vnew_data_flag := low; -- -- save bad channel data for l3 -- vbc := bad_channel_data; next_state := write_fifo; -- DO NOT enable l3 raw here l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; -- write_fifo State -- WHEN write_fifo => vstate := write_fifo_state; --- this is for debugging vnew_data_flag := low; -- reset new data flag after first write. if(output_fifo_full = '1') then next_state := write_fifo; else next_state := read_fifo; -- fifo is free to write into. Next state should be calling state if(peof = '1') then -- if end of event, reset vserr vserr := low; -- end if; end if; -- bring l3_rawdata low in here l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; --read_fifo state when read_fifo => vstate := read_fifo_state; if(input_fifo_empty = '1') then next_state := read_fifo; -- fifo is empty. need to wait else next_state := return_state; end if; -- bring l3_rawdata low in here l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; -- OTHERS -- -- should never come here WHEN OTHERS => next_state := sinit; return_state := sinit; l3_rawdata_eof <= '0'; l3_rawdata_enable <= '0'; END CASE; -- if monitor_clear, need to reset monitor counters) if(monitor_clear = '1') then for i in 8 downto 0 loop nchip(i) <= zero_monitor_word; end loop; nsmt_mismatch_count <= zero24; nsmt_zero_error <= zero24; end if; -- set the next state of signal to their respective variable signals nstate <= vstate; n_new_data_flag <= vnew_data_flag; nrs <= return_state; ns <= next_state; noutput <= voutput; neof <= veof; nchip_id <= vchip_id; nchan_id <= vchan_id; nseq_id <= vseq_id; nhdi_id <= vhdi_id; nbc <= vbc; nserr <= vserr; end process; -- The following two process block work concurrently with the above process block. One -- block reads raw data from the input FIFO process block and the other write corrected data -- to the write FIFO process block -- Read fifo block -- This process block reads raw data from the input fifo process(ps,input_fifo_empty) -- This process is used to read the input fifo variable vread: std_logic; begin vread := '0'; if(input_fifo_empty = '1') then -- Buffer is empty, therefore no read signal vread := '0'; else --Write and read fifo process case ps is when read_fifo => -- For any read_fifo state set read flag high vread := '1'; when others => vread := '0'; end case; end if; oread <= vread; -- output read signal is set to read variable end process; process(ps) -- This process is used to write to the output fifo variable vwrite: std_logic; begin vwrite := '0'; if(output_fifo_full = '1') then -- If buffer is full, we must wait vwrite := '0'; else case ps is --when we have a write enable signal, we will proceed when write_fifo=> -- to write to the ouput fifo the 23-bit word vwrite := '1'; when others => vwrite := '0'; end case; end if; owrite <= vwrite; end process; --------------------------------------------------------------------------------- --- Use this process block to determine the type of data --- Input parameters must come from another block --------------------------------------------------------------------------------- process (data_range_in,pchip_id) -- use variables to break up data_range data variable axial_low,axial_high,stereo_low,stereo_high,ninety_low,ninety_high: unsigned(3 downto 0); begin axial_low := data_range_in(3 downto 0); axial_high := data_range_in(7 downto 4); stereo_low := data_range_in(11 downto 8); stereo_high := data_range_in(15 downto 12); ninety_low := data_range_in(19 downto 16); ninety_high := data_range_in(23 downto 20); ndata_type <= undefined_type; if(pchip_id >= axial_low and pchip_id <= axial_high) then ndata_type <= axial_type; end if; if(pchip_id >= stereo_low and pchip_id <= stereo_high) then ndata_type <= stereo_type; end if; if(pchip_id >= ninety_low and pchip_id <= ninety_high) then ndata_type <= ninety_degrees_type; end if; end process; --------------------------------------------------------------------------------- --- This block monitors the number of times ERROR is high in the smt data --------------------------------------------------------------------------------- process(stream_in,monitor_clear) begin nsmt_error_count <= psmt_error_count; if(monitor_clear = '1') then nsmt_error_count <= zero24; elsif((stream_in(16) = high) or (stream_in(17) = high)) then nsmt_error_count <= psmt_error_count + 1; end if; end process; --- --- This process block is used to start a new event --- process(pevent_state,peof,event_start) begin nnew_event <= pnew_event; case pevent_state is when sinit => nnew_event <= '0'; if(event_start = '1') then nevent_state <= snew_event; else nevent_state <= sinit; end if; when snew_event => -- this is a new event nnew_event <= '0'; -- enter three wait states before reading first word nevent_state <= swait1; -- this gives L3 time to write headers when swait1 => nnew_event <= '0'; nevent_state <= swait2; when swait2 => nnew_event <= '0'; nevent_state <= sevent; when sevent => nnew_event <= '1'; if(peof = '1') then nevent_state <= sinit; else nevent_state <= sevent; end if; when others => --- never should come here null; end case; end process; --- Use this process block to clear monitor signals ------------------------------------------------------------------------------ ------------ REGISTER BLOCK --------------------- --------------------------------------------------------------------------------- reg:process(clock,reset, ns, nrs, noutput,nchip_id,nchan_id,n_new_data_flag, ndata_type,neof,nbad_channel_address,nstate,nchip_data,nmismatchbit, nsmt_error_count,nsmt_mismatch_count,nsmt_zero_error,nbc,nnew_event) begin if (reset = '0') then --Sets all outputs and counters to zero pstate <= initial_state; ps <= sinit; prs <= sinit; poutput <= zero23; pchip_id <= zero4; pchan_id <= zero7; p_new_data_flag<= '0'; pseq_id <= zero8; phdi_id <= zero3; pdata_type <= zero2; peof <= '0'; pbc <= '0'; pserr <= '0'; pbad_channel_address <= zero4&zero7; pchip_data <="000000000000"; psmt_error_count <= zero24; psmt_mismatch_count <= zero24; psmt_zero_error <= zero24; pl3_trailer <= zero24; pmismatchbit <= '0'; pnew_event <= '0'; pevent_state <= sinit; elsif (clock'event and clock = '1') then pstate <= nstate; ps <= ns; --at every clock edge there will be an output prs <= nrs; poutput <= noutput; pchip_id <= nchip_id; pchan_id <= nchan_id; p_new_data_flag<= n_new_data_flag; pseq_id <= nseq_id; phdi_id <= nhdi_id; pdata_type <= ndata_type; peof <= neof; pbc <= nbc; pserr <= nserr; pbad_channel_address <= nbad_channel_address; pchip_data <= nchip_data; psmt_error_count <= nsmt_error_count; psmt_mismatch_count <= nsmt_mismatch_count; psmt_zero_error <= nsmt_zero_error; pmismatchbit <= nmismatchbit; pl3_trailer <= nl3_trailer; pnew_event <= nnew_event; pevent_state <= nevent_state; end if; end process reg; --End of register block -- -- register block for chip counters -- process(clock,reset,nchip) begin if(reset = '0') then for i in 8 downto 0 loop pchip(i) <= zero_monitor_word; end loop; elsif(clock'event and clock='1') then pchip <= nchip; end if; end process; -- -- This process block is used to form l3 word -- process(peof,pmismatchbit,pdata_type,poutput,pseq_id,phdi_id,pbc,smt_in,pserr,pl3_trailer) variable vnew_data_flag,vend_of_event: std_logic; variable vchip_id : unsigned(3 downto 0); variable vchan_id: unsigned(6 downto 0); variable vdata_event, vseq_id: unsigned(7 downto 0); variable vhdi_id: unsigned(2 downto 0); variable vdata_type:unsigned(1 downto 0); variable veof,vbc,vmismatch,vserr: std_logic; variable vsmt_in: unsigned(2 downto 0); variable vl3_out: unsigned(24 downto 0); begin -- -- Use variables to help form data word -- vdata_type := poutput(22 downto 21); vnew_data_flag := poutput(20); veof := poutput(19); vdata_event := poutput(18 downto 11); vchip_id := poutput(10 downto 7); vchan_id := poutput(6 downto 0); veof := peof; vmismatch := pmismatchbit; vseq_id := pseq_id; vhdi_id := phdi_id; vsmt_in := smt_in; vserr := pserr; vbc := pbc; nl3_trailer <= vserr&vmismatch&vsmt_in&vseq_id&vhdi_id&vdata_event; -- if end of event we must output trailer l3 word --- event number should be in trailer if(veof = '1') then -- 1 + 1 + 1 + 3 + 8 + 3 + 8 = 25 vl3_out := veof&vserr&vmismatch&vsmt_in&vseq_id&vhdi_id&vdata_event; -- 1 + 1 + 3 else -- 1+ 1 + 2 + 8 + 4 + 7 + 2 = 25 vl3_out := veof&vbc&vdata_type&vdata_event&vchip_id&vchan_id&"00"; -- nl3_trailer <= pl3_trailer; end if; l3_correcteddata <= vl3_out; end process; ostate <= pstate; -- Ensures that we keep the outputs constant at every cycle output <= poutput; -- until a condition is met and we update the values. bad_channel_address <= pbad_channel_address; chip_data <= pchip_data; chip_monitor <= pchip; smt_monitor(0) <= to_monitorword(pl3_trailer); smt_monitor(1) <= to_monitorword(psmt_error_count); smt_monitor(2) <= to_monitorword(psmt_mismatch_count); smt_monitor(3) <= to_monitorword(psmt_zero_error); end architecture logic_design; --End of architecture block C.14: MONITOR ADDRESS SPACE -- -- This is the monitor address space -- It is 32x24 -- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; library cluster_package; use cluster_package.cluster_package.all; -- This package contains the following definitions -- smt_array is 4 x 24 -- chip_array is 9 x 24 -- centroid_array is 3 x 24 entity monitor_spacea is port(address: in unsigned(9 downto 0); monitor_latch: in std_logic; smt_counter: in smt_array; chipcounter: chip_array; axial:in centroid_array; clk,reset: in std_logic; l3_trailer: out fifoword; word_out: out fifoword; monitor_clear: out std_logic ); end entity monitor_spacea; architecture behavior of monitor_spacea is -- -- Define the following general memory map for the 1k monitor space -- -- smt counters 000-00F -- centroid counters 010-01F -- chip counters 020-02F -- empty space 030-3FF constant smt_address_space :unsigned(5 downto 0) := "000000"; constant centroid_address_space :unsigned(5 downto 0) := "000001"; constant chip_address_space :unsigned(5 downto 0) := "000010"; signal nsmt_registers,psmt_registers: smt_array; signal nchip_registers,pchip_registers: chip_array; signal ncentroid_registers,pcentroid_registers: centroid_array; constant true: std_logic := '1'; constant false: std_logic := '0'; signal nmonitor_clear,pmonitor_clear: std_logic; type smt_states is (s0,s1,s2); signal psmt,nsmt: smt_states; signal nword_out, pword_out: fifoword; --signal nbyte_out, pbyte_out: fifobyte; begin -- -- This process block attaches the monitor counters to the register array -- It is enabled on the rising edge of monitor_latch -- process(psmt,smt_counter,chipcounter,axial,monitor_latch) begin -- -- Default outputs -- -- smt_registers -- for i in 3 downto 0 loop nsmt_registers(i) <= psmt_registers(i); end loop; -- -- chip registers -- for i in 8 downto 0 loop nchip_registers(i) <= pchip_registers(i); end loop; -- -- centroid registers -- for i in 2 downto 0 loop ncentroid_registers(i) <= pcentroid_registers(i); end loop; -- -- look for the rising edge of monitor_latch -- case psmt is when s0 => nsmt <= s0; nmonitor_clear <= '0'; if(monitor_latch = '1') then nsmt <= s1; end if; when s1 => nsmt <= s2; nmonitor_clear <= '1'; for i in 3 downto 0 loop nsmt_registers(i) <= smt_counter(i); end loop; for i in 8 downto 0 loop nchip_registers(i) <= chipcounter(i); end loop; for i in 2 downto 0 loop ncentroid_registers(i) <= axial(i); end loop; when s2 => nmonitor_clear <= '1'; if(monitor_latch = '1') then nsmt <= s2; else nsmt <= s0; end if; when others => nsmt <= s0; nmonitor_clear <= '0'; end case; end process; -- -- This process block sets the data output to the addressed monitor space -- process(address,psmt_registers,pchip_registers,pcentroid_registers) variable vaddress_high: unsigned(5 downto 0); variable vaddress_low: unsigned(3 downto 0); variable vword_out: monitor_word; begin vaddress_high := address(9 downto 4); vaddress_low := address(3 downto 0); vword_out := zero_monitor_word; -- -- use address_high to select memory space -- -- use address_low to select specific word -- case vaddress_high is when smt_address_space => case vaddress_low is when address0 => vword_out := psmt_registers(0); when address1 => vword_out := psmt_registers(1); when address2 => vword_out := psmt_registers(2); when address3 => vword_out := psmt_registers(3); when others => vword_out := zero_monitor_word; end case; when chip_address_space => case vaddress_low is when address0 => vword_out := pchip_registers(0); when address1 => vword_out := pchip_registers(1); when address2 => vword_out := pchip_registers(2); when address3 => vword_out := pchip_registers(3); when address4 => vword_out := pchip_registers(4); when address5 => vword_out := pchip_registers(5); when address6 => vword_out := pchip_registers(6); when address7 => vword_out := pchip_registers(7); when address8 => vword_out := pchip_registers(8); when others => vword_out := zero_monitor_word; end case; when centroid_address_space => case vaddress_low is when address0 => vword_out := pcentroid_registers(0); when address1 => vword_out := pcentroid_registers(1); when address2 => vword_out := pcentroid_registers(2); when others => vword_out := zero_monitor_word; end case; when others => vword_out := zero_monitor_word; end case; nword_out <= to_fifoword(vword_out); end process; -- -- This process block implements the registers for the monitor space -- process(nsmt_registers,nchip_registers,ncentroid_registers,clk,reset) begin if(reset='0') then for i in 3 downto 0 loop psmt_registers(i) <= zero_monitor_word; end loop; for i in 8 downto 0 loop pchip_registers(i) <= zero_monitor_word; end loop; for i in 4 downto 0 loop pcentroid_registers(i) <= zero_monitor_word; end loop; elsif(clk='1' and clk'event) then for i in 3 downto 0 loop psmt_registers(i) <= nsmt_registers(i); end loop; for i in 8 downto 0 loop pchip_registers(i) <= nchip_registers(i); end loop; for i in 2 downto 0 loop pcentroid_registers(i) <= ncentroid_registers(i); end loop; end if; end process; -- -- This process block implements registers -- process(nsmt, nmonitor_clear, clk,reset) begin if(reset = '0') then psmt <= s0; pmonitor_clear <= '0'; pword_out <= zero_fifoword; elsif(clk = '1' and clk'event) then psmt <= nsmt; pmonitor_clear <= nmonitor_clear; pword_out <= nword_out; end if; end process; -- -- This process block is used to construct l3 trailer -- process(smt_counter(0)) variable vl3temp: fifoword; begin vl3temp := to_fifoword(smt_counter(0)); --- 5 + 2 + 3 + 22 = l3_trailer <= "11110"&vl3temp(23 downto 22)&"000"&vl3temp(21 downto 0); end process; monitor_clear <= pmonitor_clear; word_out <= pword_out; end architecture; C.15: CLUSTER PACKAGE -- This code is for the package- for clustering the data for the counters -- this is just a package declaration common for all the other files library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; package cluster_package is type monitor_word is array(23 downto 0) of std_logic; type fifoword is array(31 downto 0) of std_logic; type fifobyte is array(7 downto 0) of std_logic; type smt_array is array(3 downto 0) of monitor_word; type chip_array is array(8 downto 0) of monitor_word; type centroid_array is array(2 downto 0) of monitor_word; constant zero_monitor_word: monitor_word := "000000000000000000000000"; constant zero_fifoword: fifoword := "00000000000000000000000000000000"; constant zero_fifobyte: fifobyte := "00000000"; constant address0: unsigned(3 downto 0) := "0000"; constant address1: unsigned(3 downto 0) := "0001"; constant address2: unsigned(3 downto 0) := "0010"; constant address3: unsigned(3 downto 0) := "0011"; constant address4: unsigned(3 downto 0) := "0100"; constant address5: unsigned(3 downto 0) := "0101"; constant address6: unsigned(3 downto 0) := "0110"; constant address7: unsigned(3 downto 0) := "0111"; constant address8: unsigned(3 downto 0) := "1000"; constant address9: unsigned(3 downto 0) := "1001"; constant addressa: unsigned(3 downto 0) := "1010"; constant addressb: unsigned(3 downto 0) := "1011"; constant addressc: unsigned(3 downto 0) := "1100"; constant addressd: unsigned(3 downto 0) := "1101"; constant addresse: unsigned(3 downto 0) := "1110"; constant addressf: unsigned(3 downto 0) := "1111"; -- define data_types constant undefined_type: unsigned(1 downto 0) := "00"; constant stereo_type : unsigned(1 downto 0) := "01"; constant axial_type: unsigned(1 downto 0) := "10"; constant ninety_degrees_type: unsigned(1 downto 0) := "11"; function to_fifoword(a: fifobyte) return fifoword; function to_fifoword(a: monitor_word) return fifoword; function to_monitorword(a: unsigned(23 downto 0)) return monitor_word; function add_one(a: monitor_word) return monitor_word; end package; package body cluster_package is function to_fifoword(a:fifobyte) return fifoword is variable result: fifoword; begin for i in 31 downto 8 loop result(i) := '0'; end loop; for i in 7 downto 0 loop result(i) := a(i); end loop; return result; end function; -- function to_fifoword(a:monitor_word) return fifoword is variable result: fifoword; begin for i in 31 downto 24 loop result(i) := '0'; end loop; for i in 23 downto 0 loop result(i) := a(i); end loop; return result; end function; -- function to_monitorword(a:unsigned(23 downto 0)) return monitor_word is variable result: monitor_word; begin for i in 23 downto 0 loop result(i) := a(i); end loop; return result; end function; -- function add_one(a:monitor_word) return monitor_word is variable result: monitor_word; variable temp: unsigned(23 downto 0); variable i: integer; begin for i in 23 downto 0 loop temp(i) := a(i); end loop; temp := temp + 1; for i in 23 downto 0 loop result(i) := temp(i); end loop; return result; end function; -- end; C.16: CLUSTER FINDER ------------------------------------------------------------------------------ -- Revision 2 Cluster Finder Algorithm -- Based on 2-15-2000 Specification Document ----------------------------------------------------------------------------- -- Initial Design : Reginald Perry (6-12-2000) ----------------------------------------------------------------------------- -- Add monitor counter - 7/17/2000 RJP -- Add end of event bit - 7/17/2000 RJP library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; library cluster_package; use cluster_package.cluster_package.all; entity cluster_finder is port(data_in: in unsigned(22 downto 0); -- input data word from fifo data_threshold_1,data_threshold_2: in unsigned(7 downto 0); -- read as inputs cluster_type: in unsigned(0 downto 0); -- use 3 or 5 strips in scalculation -- -- altera compiler does not like unsigned without vector. -- Need to have two bits until -- we can check this out input_fifo_empty,output_axialfifo_full,clk, reset : in std_logic; input_fifo_read,output_axialfifo_write: out std_logic; ad2: out unsigned(10 downto 0); -- address bus d1,d2,d3,d4,d5: out unsigned(7 downto 0); current_type: out unsigned(1 downto 0); -- current data type end_of_event_out: out std_logic; -- this is the end of event bit calculation_type: out unsigned(0 downto 0); -- this is the type of calculation l3_enable: out std_logic; -- this is used to enable l3 centroid_counters: out centroid_array; l3out:out unsigned(31 downto 0) ); -- inputs for data_threshold end entity cluster_finder; architecture behavior of cluster_finder is -- define major states type mystates is (sreset, sread,sread_fifo,sload_fifo,scheck_for_eof, sinit,smain,snext,soutpeak,scalculate,swrite,swrite_fifo, sl3_wait); type l3states is (s0,s1,s2,s3,s4,s5,s6); -- data types are now defined in cluster_package -- constant axial: unsigned(1 downto 0) := "01"; -- constant stereo: unsigned(1 downto 0) := "10"; -- constant z_axis: unsigned(1 downto 0) := "11"; -- constant undefined: unsigned(1 downto 0) := "00"; signal ns, ps,nreturn_state,preturn_state: mystates; signal nl3s,pl3s: l3states; -- counter used to keep track of number of strips read signal nstrip_count, pstrip_count: unsigned(7 downto 0); -- signals used for data and address registers signal nd1,nd2,nd3,nd4,nd5,ndata_shadow1, ndata_shadow2: unsigned(7 downto 0); signal pd1,pd2,pd3,pd4,pd5,pdata_shadow1, pdata_shadow2: unsigned(7 downto 0); signal nad1,nad2,nad3,nad4,nad5,naddress_shadow1, naddress_shadow2: unsigned(10 downto 0); signal pad1,pad2,pad3,pad4,pad5,paddress_shadow1, paddress_shadow2: unsigned(10 downto 0); -- these signals are used to keep track of the current data type signal nnext_address,pnext_address: unsigned(10 downto 0); signal ncurrent_type,pcurrent_type: unsigned(1 downto 0); signal nfirst_read,pfirst_read,data_compare,valid_cluster_peak: std_logic; signal pdata,ndata: unsigned(22 downto 0); -- these signals are for the end of event bit signal neof,peof,nl3_wait,pl3_wait: std_logic; --- these signals are used for monitoring signal naxial_counter,paxial_counter,nstereo_counter, pstereo_counter: unsigned(23 downto 0); signal nninety_counter, pninety_counter: unsigned(23 downto 0); -- l3buffer signal pl3out,nl3out: unsigned(31 downto 0); -- these constants are used with the data registers constant zero_data_reg: unsigned(7 downto 0) := "00000000"; constant zero_address_reg: unsigned(10 downto 0) := "00000000000"; constant zero23:unsigned(22 downto 0) := "00000000000000000000000"; constant zero24:unsigned(23 downto 0) := "000000000000000000000000"; constant zero32: unsigned(31 downto 0) := "00000000000000000000000000000000"; constant true: std_logic := '1'; constant false: std_logic := '0'; -- -- l3stuff begin process(ps,preturn_state,pd1,pd2,pd3,pd4,pd5,pad1,pad2,pad3,pad4,pad5, paddress_shadow1,paddress_shadow2,pdata_shadow1,pdata_shadow2, pnext_address,pcurrent_type,pdata,preturn_state,pfirst_read,pdata, pstrip_count,data_compare,valid_cluster_peak,data_threshold_1, data_threshold_2,input_fifo_empty,cluster_type,paxial_counter, pstereo_counter,pninety_counter,pl3_wait) variable vtype: unsigned(1 downto 0); variable veof,vnew_data_flag,end_of_cluster: std_logic; variable vdata: unsigned(7 downto 0); variable vaddress: unsigned(10 downto 0); variable vl3out:unsigned(31 downto 0); begin -- set default outputs -- state information ns <= ps; nreturn_state <= preturn_state; -- hold onto return state -- save data buffers nd1 <= pd1; nd2 <= pd2; nd3 <= pd3; nd4 <= pd4; nd5 <= pd5; ndata_shadow1 <= pdata_shadow1; ndata_shadow2 <= pdata_shadow2; -- save address buffers nad1 <= pad1; nad2 <= pad2; nad3 <= pad3; nad4 <= pad4; nad5 <= pad5; naddress_shadow1 <= paddress_shadow1; naddress_shadow2 <= paddress_shadow2; -- parse current input word in parts. Use variables for this. vtype := pdata(22 downto 21); vnew_data_flag := pdata(20); -- variable defined as std_logic veof := pdata(19); -- variable defined as std_logic vdata := pdata(18 downto 11); vaddress := pdata(10 downto 0); -- save eof for next block neof <= veof; -- -- set defaults for these signals -- ncurrent_type <= pcurrent_type; -- current data type nnext_address <= pnext_address; nfirst_read <= pfirst_read; -- flag to indicate we are coming out of a reset state -- this prevents a centriod calculation before the first read. ndata <= pdata; -- save data -- This implements the main FSM case ps is -- -- Reset state -- This is the first state AFTER the initial reset -- when sreset => -- -- Need to load data parameters here eventually. -- For now, just go to the first read -- ns <= sread; ncurrent_type <= axial_type; -- default to axial type to give memory something to access nreturn_state <= sinit; -- this statement is really not needed since this is the first read nfirst_read <= true; -- but let's help the synthesis tool anyway. -- Read state when sread => if(input_fifo_empty = true) then ns <= sread; -- fifo is empty. Need to wait for some data else ns <= sread_fifo; -- data is ready Go to next state to read_fifo end if; -- Read fifo state -- add this "wait" state to allow data to be read from input fifo when sread_fifo => ns <= sload_fifo; -- -- Data should be available at fifo. Load into an internal register data -- when sload_fifo => ndata <= data_in; ns <= scheck_for_eof; -- let's go check for the eof -- -- probably we can combine sread_fifo and sload_fifo. Look at this later -- -- This state checks for an eof -- when scheck_for_eof => -- if veof=1 then this is the end of a cluster -- if veof=0 then end of cluster is initial reset to 0 end_of_cluster :=veof; -- -- Check for a change of type if(vtype /= pcurrent_type) then end_of_cluster := true; ncurrent_type <= vtype; -- save new data type as next current_type end if; -- if data is less than threshold then end of cluster. Data_threshold_1 is an input if(vdata < data_threshold_1) then end_of_cluster := true; end if; -- if current_address /= next_address then end of cluster -- need to set next_address based on this outcome if(vaddress /= pnext_address) then end_of_cluster := true; nnext_address <= vaddress + 1; else nnext_address <= pnext_address + 1; end if; -- -- if this is the first read then we don't want to store -- a hit in the output fifo -- if(pfirst_read = true) then nfirst_read <= false; ns<= sinit; elsif(end_of_cluster = '1') then -- -- This is the start of a new cluster. -- Need to calculate centroid on old cluster. -- The current data word will be used in the new cluster -- ns <= scalculate; nreturn_state <= sinit; -- after calculate need to initialize current data word else ns <= preturn_state; -- this is not the end of a cluster. continue cluster finding algorithm end if; -- Initialization State. We are starting the search for a new cluster when sinit => -- init data registers nd1 <= zero_data_reg; nd2 <= zero_data_reg; nd3 <= vdata; nd4 <= zero_data_reg; nd5 <= zero_data_reg; -- init address registers nad1 <= zero_address_reg; nad2 <= zero_address_reg; nad3 <= vaddress; nad4 <= zero_address_reg; nad5 <= zero_address_reg; -- init shadow registers ndata_shadow2 <= zero_data_reg; ndata_shadow1 <= zero_data_reg; naddress_shadow2 <= zero_address_reg; naddress_shadow1 <= zero_address_reg; -- go read the next word and return to smaim ns <= sread; nreturn_state <= smain; -- this is the main state. Compare the next data word to the current cluster center when smain => -- next state will be sread ns <= sread; if(data_compare = '1') then -- -- if data is greater than or equal to current peak then move data as cluster peak -- need to shift all other data words to the left by one slot nd1 <= pd2; nd2 <= pd3; nd3 <= vdata; -- need to also shift addresses nad1 <= pad2; nad2 <= pad3; nad3 <= vaddress; nreturn_state <= smain; -- come back to this state else -- Data is less than current cluster peak. Store this value in d4. nd4 <= vdata; nad4 <= vaddress; nreturn_state <= snext; --- need to go to snext state end if; -- -- this is the next state. This looks at the D5 register -- when snext => -- next state will be sread ns <= sread; if(data_compare = '1') then -- if data is greater than or equal to current cluster peak -- shift d3 to d1 and d4 to d2 and new peak (nd3) gets vdata -- must also remember to zero out nd4 and nd5 nd1 <= pd3; nd2 <= pd4; nd3 <= vdata; nd4 <= zero_data_reg; nd5 <= zero_data_reg; -- also need to change the addresses nad1 <= pad3; nad2 <= pad4; nad3 <= vaddress; nad4 <= zero_address_reg; nad5 <= zero_address_reg; nreturn_state <= smain; else -- vdata is less than current cluster peak -- save vdata in nd5 also need to set up "shawdow" registers nd5 <= vdata; nad5 <= vaddress; -- need to setup shadow registers for "out-peak" case ndata_shadow1 <= pd4; ndata_shadow2 <= vdata; naddress_shadow1 <= pad4; naddress_shadow2 <= vaddress; -- return state should be out peak nreturn_state <= soutpeak; end if; -- This is the outpeak case. -- That is, the current cluster address is out of the range of the -- cluster peak. However, we need to save the last two values in case -- we come across a case where -- vdata > pd3. when soutpeak => -- next state will be sread ns <= sread; -- -- This is where we check the data against the current cluster peak -- if(data_compare = '1') then -- data is greater than current cluster peak. -- Need to move shadow registers into real registers -- don't forget to zero d4 and d5 nd1 <= pdata_shadow1; nd2 <= pdata_shadow2; nd3 <= vdata; nd4 <= zero_data_reg; nd5 <= zero_data_reg; -- same goes for the addresses nad1 <= paddress_shadow1; nad2 <= paddress_shadow2; nad3 <= vaddress; nad4 <= zero_address_reg; nad5 <= zero_address_reg; nreturn_state <= smain; --- return now goes to smaim else -- -- din is not greater than current peak. -- shift shadow registers and return to this state -- ndata_shadow1 <= pdata_shadow2; ndata_shadow2 <= vdata; naddress_shadow1 <= paddress_shadow2; naddress_shadow2 <= vaddress; nreturn_state <= soutpeak; end if; -- -- This is the centriod calculate state -- Actually centroid is always being calculated -- we just need to determine if we send it on to the -- hit filter. -- when scalculate => -- -- -- if(valid_cluster_peak = true) then --- this signal is generated by another process block -- -- need to and increment counters case vtype is when axial_type => naxial_counter <= paxial_counter + 1; when stereo_type => nstereo_counter <= pstereo_counter + 1; when ninety_degrees_type => nninety_counter <= pninety_counter + 1; when others => null; end case; ns <= swrite; else -- -- this is not a valid peak. Throw away this cluster and start over -- ns <= sinit; end if; when swrite => -- dummy state to see if output fifo is not empty if(output_axialfifo_full = true) then ns <= swrite; else ns <= swrite_fifo; end if; when swrite_fifo => -- output fifo is written during this cycle ns <= sl3_wait; -- let's wait for l3 to finish when sl3_wait => if(pl3_wait = '1') then ns <= sl3_wait; else ns <= sinit; end if; when others => -- we should never come here. Therefore go to sreset ns <= sreset; end case; end process; -- -- this state machine is used to read a word from the input fifo -- process(ps) variable vread: std_logic; begin vread := false; case ps is when sread_fifo => vread := true; when others => vread := false; end case; input_fifo_read <= vread; end process; -- -- this state machine is used to write a word to the output fifo -- process(ps) variable vwrite: std_logic; begin vwrite := false; case ps is when swrite_fifo => vwrite := true; when others => vwrite := false; end case; output_axialfifo_write<= vwrite; -- do this as a mealy machine to save a cycle end process; -- -- This process block counts the number of strips in the current cluster (-1) -- process(ps,pstrip_count) variable vcnt : unsigned(7 downto 0); begin vcnt := pstrip_count; case ps is when sinit => vcnt := zero_data_reg; when smain|snext|soutpeak => -- only increment this counter when we have new data vcnt := vcnt + 1; when others => null; end case; nstrip_count <= vcnt; end process; -- -- This process block compares the data against the current peak -- process(pdata,pd3) variable vdata:unsigned(7 downto 0); begin vdata := pdata(18 downto 11); -- -- compare data word to current cluster center -- if(vdata < pd3) then data_compare <= '0'; else data_compare <= '1'; end if; end process; -- -- This process block compares pd3 against data_threshold_2 -- process(pd3,data_threshold_2) variable vdata:unsigned(7 downto 0); begin vdata := pd3; -- -- compare data word to current cluster center -- if(vdata < data_threshold_2) then valid_cluster_peak <= false; -- current peak is less than data_threshold_2 -- invalid peak. else valid_cluster_peak <= true; -- we have a valid peak here. end if; end process; -- -- Register process block for state information -- process (ns,nreturn_state,nl3s,clk, reset) begin if( reset = '0') then ps <= sreset; preturn_state <= sreset; pl3s <= s0; elsif(clk = '1' and clk'event) then ps <= ns; preturn_state <= nreturn_state; pl3s <= nl3s; end if; end process; -- -- Register process block for misc signals -- process (ncurrent_type,nnext_address, pfirst_read, clk, reset) begin if( reset = '0') then pcurrent_type <= undefined_type; pnext_address <= zero_address_reg; pfirst_read <= '0'; elsif(clk = '1' and clk'event) then pcurrent_type <= ncurrent_type; pnext_address <= nnext_address; pfirst_read <= nfirst_read; end if; end process; -- -- Register process block to shadow address and data registers also the data is saved here -- process(nd1,nd2,nd3,nd4,nd5,nad1,nad2,nad3,nad4,nad5,nstrip_count, nl3out,nl3_wait,naddress_shadow1,naddress_shadow2, ndata_shadow1,ndata_shadow2,ndata, clk, reset) begin if( reset = '0') then pd1 <= zero_data_reg; pd2 <= zero_data_reg; pd3 <= zero_data_reg; pd4 <= zero_data_reg; pd5 <= zero_data_reg; pad1 <= zero_address_reg; pad2 <= zero_address_reg; pad3 <= zero_address_reg; pad4 <= zero_address_reg; pad5 <= zero_address_reg; pdata_shadow1 <= zero_data_reg; pdata_shadow2 <= zero_data_reg; paddress_shadow1 <= zero_address_reg; paddress_shadow2 <= zero_address_reg; pdata <= zero23; pstrip_count <= zero_data_reg; pl3out <= zero32; peof <= '0'; pl3_wait <= '0'; elsif( clk'event and clk = '1') then pd1 <= nd1; pd2 <= nd2; pd3 <= nd3; pd4 <= nd4; pd5 <= nd5; pad1 <= nad1; pad2 <= nad2; pad3 <= nad3; pad4 <= nad4; pad5 <= nad5; pdata_shadow1 <= ndata_shadow1; pdata_shadow2 <= ndata_shadow1; paddress_shadow1 <= naddress_shadow1; paddress_shadow2 <= naddress_shadow1; pdata <= ndata; pstrip_count <= nstrip_count; pl3out <= nl3out; peof <= neof; pl3_wait <= nl3_wait; end if; end process; -- Registers for counters process(clk,reset,naxial_counter,nstereo_counter,nninety_counter) begin if(reset = '0') then paxial_counter <= zero24; pstereo_counter <= zero24; pninety_counter <= zero24; elsif(clk'event and clk='1') then paxial_counter <= naxial_counter; pstereo_counter <= nstereo_counter; pninety_counter <= nninety_counter; end if; end process; -- this process block takes care of l3, we will need multiple cycles to write all the data process(ps, pl3s,pd1,pd2,pd3,pd4,pd5,pad1,pad2,pad3,pad4,pad5,data_threshold_1,data_threshold_2,pstrip_count, valid_cluster_peak, pcurrent_type, cluster_type) variable vl3out: unsigned(31 downto 0); begin -- default outputs nl3_wait <= '0'; vl3out := zero32; nl3s <= pl3s; case pl3s is when s0 => l3_enable <= '0'; if(ps = scalculate) then nl3_wait <= '1'; --- tell main fsm to hold nl3s <= s1; -- need to set up first l3 output word vl3out(31 downto 28) := "0000"; vl3out(27 downto 20) := data_threshold_2; vl3out(19 downto 18) := pcurrent_type; vl3out(17) := cluster_type(0); --- only a single bit vl3out(16 downto 9) := data_threshold_1; vl3out(8 downto 1) := pstrip_count; vl3out(0) := '1'; else nl3_wait <= '0'; nl3s <= s0; end if; when s1 => nl3_wait <= '1'; l3_enable <= '1'; -- write the previous word into l3 using l3_enable --do not register vl3out(31 downto 23) := "000000000"; vl3out(22 downto 21) := pcurrent_type; vl3out(20 downto 13) := pd2; vl3out(12 downto 2) := pad2; vl3out(1 downto 0) := "00"; nl3s <= s2; when s2 => nl3_wait <='1'; l3_enable <= '1'; --- write the remaining data out vl3out(31 downto 23) := "000000000"; vl3out(22 downto 21) := pcurrent_type; vl3out(20 downto 13) := pd3; vl3out(12 downto 2) := pad3; vl3out(1 downto 0) := "00"; nl3s <= s3; when s3 => nl3_wait <='1'; l3_enable <= '1'; --- write the remaining data out vl3out(31 downto 23) := "000000000"; vl3out(22 downto 21) := pcurrent_type; vl3out(20 downto 13) := pd4; vl3out(12 downto 2) := pad4; vl3out(1 downto 0) := "00"; nl3s <= s4; when s4 => nl3_wait <='1'; l3_enable <= '1'; --- write the remaining data out vl3out(31 downto 23) := "000000000"; vl3out(22 downto 21) := pcurrent_type; vl3out(20 downto 13) := pd5; vl3out(12 downto 2) := pad5; vl3out(1 downto 0) := "00"; nl3s <= s5; when s5 => nl3_wait <='0'; -- we can let main FSM restart now l3_enable <= '1'; --- write the remaining data out vl3out(31 downto 23) := "000000000"; vl3out(22 downto 21) := pcurrent_type; vl3out(20 downto 13) := pd1; vl3out(12 downto 2) := pad1; vl3out(1 downto 0) := "00"; nl3s <= s6; -- need one more state to write out last word when s6 => nl3_wait <='0'; l3_enable <= '1'; --- write out last word nl3s <= s0; when others => null; end case; nl3out <= vl3out; -- this will save l3out for writing into l3 end process; -- attach address and data registers to output buffers d1 <= pd1; d2 <= pd2; d3 <= pd3; d4 <= pd4; d5 <= pd5; ad2 <= pad2; l3out <= pl3out; current_type <= pcurrent_type; end_of_event_out <= peof; calculation_type <= cluster_type; -- attach counters centroid_counters(0) <= to_monitorword(paxial_counter); centroid_counters(1) <= to_monitorword(pstereo_counter); centroid_counters(2) <= to_monitorword(pninety_counter); end behavior; C.17: CENTROID CALCULATOR ---------------------------------------------------------------- -- File: centroid_calculator.vhd -- Description: VHDL code to calculate the three or five strip centroid. -- For the five strip case we are given five (5) eight bit values - -- d1,d2,d3,d4,d5 -- The centroid is usually given by (d1+2d2+3d3+4d4+5d5)/(d1+d2+d3+d4+d5) -- in this case we are shifting the result so it is centered around d2 -- so the numerator becomes -d1+0d2+d3+2d4+3d5 -- For the three strip case: the equation is -d1+0d2+d3/d1+d2+d3 -- -- Originally Created: 6/4/00 -- (Reginald J. Perry - FAMU-FSU College of Engineering) -- Add l3 logic: 7/17/2000 RJP -- Modified : by Shweta Lolage -- Changes in the 3 cluster centroid calculations ------------------------------------------------------------------ --- normal initialization stuff library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- -- define entity -- entity centroid_calculator is -- -- The maximum value is given by 5*255 which will need 8+3+1=12 bits to save --- (need one bit for the sign). We'll assume the d's are unsigned values. -- Therefore, we will need N+4 bits for the num and den results. port(d1,d2,d3,d4,d5: in signed(7 downto 0); threshold_range_in:in unsigned(35 downto 0); -- this is threshold data address_d2: in signed(10 downto 0); -- this is the original address of d2 calculation_type: in std_logic; centroid_type: in signed(1 downto 0); end_of_event_bit: in signed(0 downto 0); l3_trailer: in signed(31 downto 0); l3_out: out signed(31 downto 0); centroid_out: out signed(17 downto 0) ); end entity centroid_calculator; architecture behavior of centroid_calculator is signal num,den: signed(11 downto 0); constant three_strip_centroid: std_logic := '0'; constant five_strip_centroid: std_logic := '1'; constant high: std_logic := '1'; constant low: std_logic := '0'; constant zero9 : signed(8 downto 0) := "000000000"; -- these signals are needed by the divider circuit -- signal q,qint: signed(3 downto 0); signal y3,y3m,y2,y2m,y1,y1m: signed(11 downto 0); signal centroid,sum3,sum2,sum1,sum0: signed(12 downto 0); -- These signals and constants are used to calculate the quantized pulse areas signal centroid_pulse_area: signed(1 downto 0); signal level1_check,level2_check,level3_check: std_logic; signal level_check: std_logic_vector(2 downto 0); constant level0 : signed(1 downto 0) := "00"; constant level1 : signed(1 downto 0) := "01"; constant level2 : signed(1 downto 0) := "10"; constant level3 : signed(1 downto 0) := "11"; begin -- This process block provides the sums for the numerator and denominator summer: process(d1,d2,d3,d4,d5,calculation_type) -- Create variables to temporarily save results variable s1,s2,s3,s4,s5 : signed(8 downto 0); variable temp1,temp1a,temp2,temp3 : signed(9 downto 0); variable temp32,temp5 : signed(10 downto 0); variable parea,temp4,temp6,temp7 : signed(11 downto 0); variable temp1b,temp2b : signed (9 downto 0); variable temp3b : signed (10 downto 0); begin -- -- s's are used to add a sign bit to the d's -- s1 := "0"&d1; s2 := "0"&d2; s3 := "0"&d3; s4 := "0"&d4; s5 := "0"&d5; -- define temporary variables needed by both the three and five strip calculator temp1 := s1+s2; -- this sum will be 10 bits (d1+d2) temp2 := s3-s1; -- this sum will be 10 bits (d3-d1) -- Use two separate adders for three and five strip centroid calculation -- this may save some time in the calculation if(calculation_type = five_strip_centroid) then temp3 := s4+s5; -- this sum will be 10 bits (d4+d5) temp32 := temp3&"0"; -- this is 2xtemp3 = 2(d4+d5); it will be 11 bits temp4 := ("00"&s5)+temp32; -- this is 2d4 + 3d5: sum will be 12 bits temp5 := temp1 + temp3; -- this is d1+d2+d4+d5: sum will be 11 bits den <= ("000"&s3)+temp5; -- this is d1+d2+d3+d4+d5: need 12 bits temp7 := "00"&temp2; -- bit extend temp2 from 10 to 12 bits num <= temp7+temp4; -- this is -d1+d3+2d4+3d5: need 12 bits else -- this is the three strip case. num is -d2+d4 and den = d2+d3+d4 temp1b := s4 - s2; -- this will be num = -d2+d4 num <= "000"&temp1b; -- sign extend to 12 bits temp2b := s2 + s4; -- the sum of d2 + d4 , for the den temp1a := "00"&d3; -- need to sign extend d3 to add it to temp1 den <= "0"&(temp2b+temp1a); end if; end process summer; -- These process blocks implements the divider circuit. -- The design consists of four identical process blocks with a 2x1 mux -- Each process calculates yx - b where yx the result from the previous -- process block. For the first process block, yx=a. If the result of yx-a -- is greater than 0 (i.e. positive) -- then this result is given to the next process -- block otherwise yx is propagated. -- A mux is used to select between the two possiblities. -- -- p3:process(num,den) begin sum3 <= num - den; -- -- the "sign bit" is stored in sum(12) and saved as qint(3) -- qint(3) <= sum3(12); end process; -- -- if qint(3) is 1, then the result is negative and we DONT want to keep the subtraction result -- in this case we'll send yx (num in this case) to the next process block. If qint = 0 , then -- yx >= b and we want to keep the subtraction. -- with qint(3) select y3m <= num when '1', sum3(11 downto 0) when '0', num when others; -- -- We need to shift the result from above to the left by one bit so we can calculate the next -- bit of the division. We could also accomplish this by shifting den one bit to the right. -- y3 <= y3m(10 downto 0) & '0'; -- -- This process block is identical to the above except num has been -- replaced with y3 and -- the appropriate substitutions have been made for sum, y, and qint. -- p2:process(y3,den) begin sum2 <= y3 - den; qint(2) <= sum2(12); end process; with qint(2) select y2m <= y3 when '1', sum2(11 downto 0) when '0', y3 when others; y2 <= y2m(10 downto 0) & '0'; -- -- This process block is identical to the above except y3 -- has been replaced with y2 and -- the appropriate substitutions have been made for sum, y, and qint. -- p1:process(y2,den) begin sum1 <= y2 - den; qint(1) <= sum1(12); end process; with qint(1) select y1m <= y2 when '1', sum1(11 downto 0) when '0', y2 when others; y1 <= y1m(10 downto 0) & '0'; -- -- This process block is identical to the above except -- y2 has been replaced with y1 and -- the appropriate substitutions have been made for sum, y, and qint. -- p0:process(y1,den) begin sum0 <= y1 - den; qint(0) <= sum0(12); end process; inv:for I in 3 downto 0 generate q(i) <= not qint(i); end generate inv; -- q's now contain the result of the division. -- Need to add this result to the original address of d2 process(address_d2,q) variable tempa, tempb: signed(12 downto 0); constant zero10: signed(9 downto 0) := "0000000000"; begin -- the result should be 13 bits -- original 11 bits plus two extra bits -- let's use a couple of variables so we don't get lost tempa := address_d2&"00"; tempb := zero10&q(3 downto 1); centroid <= tempa + tempb; end process; -- This process block will calculate the two bit pulse area threshold values --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- process (threshold_range_in,den) -- use variables to break up data_range data variable level1_low,level2_low,level3_low:unsigned(11 downto 0); variable parea:signed(1 downto 0); constant code_level0:std_logic_vector(2 downto 0) := "000"; constant code_level1: std_logic_vector(2 downto 0) := "001"; constant code_level2: std_logic_vector(2 downto 0) := "011"; constant code_level3 : std_logic_vector(2 downto 0) := "111"; begin -- implement this like a coarse approximation ADC -- Check input data against threshold levels and then use an encoder to -- convert thermometer code to binary code level1_low := threshold_range_in(11 downto 0); level2_low := threshold_range_in(23 downto 12); level3_low := threshold_range_in(35 downto 24); -- make the default level 3 level1_check <= high; level2_check <= high; level3_check <= high; if(den < level1_low) then level1_check <= low; end if; if(den < level2_low) then level2_check <= low; end if; if(den < level3_low) then level3_check <= low; end if; level_check <= level3_check&level2_check&level1_check; case level_check is when code_level0 => parea := level0; when code_level1 => parea := level1; when code_level2 => parea := level2; when code_level3 => -- this is the default condition parea := level3; when others => parea := level3; end case; centroid_pulse_area <= parea; end process; -- this process block is for l3 for the centroids process(l3_trailer,address_d2,centroid_pulse_area,centroid_type,end_of_event_bit) variable vsmt,vhdi_id: signed(2 downto 0); variable vseq_id: signed(7 downto 0); begin vsmt := l3_trailer(21 downto 19); vhdi_id := l3_trailer(10 downto 8); vseq_id := l3_trailer(18 downto 11); if(end_of_event_bit(0) = '1') then l3_out <= l3_trailer; else -- 1+ 3 + 2 + 2 + 8 + 3 + 13 = l3_out <= "0"&vsmt¢roid_type¢roid_pulse_area&vseq_id&vhdi_id¢roid; end if; end process; -- centroid out is the end_of_event, datatype, centroid_pulse_area and centroid -- 1 + 2 + 2 + 13 centroid_out <= end_of_event_bit(0)¢roid_type¢roid_pulse_area¢roid; end architecture behavior; C.18: HIT CONTROL BLOCK ------------------------------------------------------------------- --File:hit_control_block.vhd -- To implement the control logic for the hit filter. -- Originally created by : Shweta Lolage date - 05/15/2000 --Modifications by Shweta : - 06/02/2000 -- modified by Shweta lolage on 06/15/2000 to remove all unnecessary registered signals -- modified to include one state to accommodate a control signal to read the masked register -- by Shweta Lolage - 09/04/2000 -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity hit_control_block is port (road_write,done,event_start : in std_logic; -- road_write signal from the road data handler -- DONE signal is from the pointer block indicating --that it is through with the hits for that particular centroid. -- event _start is a global signal marking the start of an event clock,reset : in std_logic; last_road : in std_logic; --signal indicating end of road data fifoempty : in std_logic; -- active low signal datatype : in std_logic_vector (2 downto 0); -- the end of event tagged with the datatype of the centroid -- coming from the centroid finder centroid : in unsigned (12 downto 0); -- centroids from the centroid finder road,mask : out unsigned (5 downto 0); -- the signals to the ROMs to get the corrected load road signal -- and final mask register read_comp,read_hitreg,input_fifo_enable,hits_busy : out std_logic; --the read_comp signal is to read the output from the comparators -- this read_hitreg signal is to read the masked hit register -- the input_fifo_enable signal is a read fifo signal -- to the centroid's fifo -- the hits_busy signal is to indicate that the -- hitfilter has started pulling out -- the centroids and is busy processing hits z_write : out std_logic; -- fifo enable for the z-axis fifo a_centroid_comp : out unsigned (13 downto 0); -- the extra bit is for the last centroid or end of event bit for the L3 z_centroid_fifo : out unsigned (13 downto 0); road_event_count : out unsigned (7 downto 0); -- this is the internal event counter for the hitfilter count : out unsigned(5 downto 0) --this output indicates the number of comparators loaded with road_data ); end entity hit_control_block; -- Architecture Body architecture behavior of hit_control_block is type states is (sevent,sfirstload,snext,sload,slast_road,sdecide, scentroid_write,scomp_read,shitreg_read,swait,sdata_wait); signal ncount,pcount,vcount : unsigned (5 downto 0); signal nstate, pstate : states; signal nroad,proad,nmask,pmask: unsigned (5 downto 0); signal nread_comp,pread_comp: std_logic; signal nread_hitreg,pread_hitreg: std_logic; signal ndone,pdone : std_logic; signal nhits_busy,phits_busy : std_logic; signal ninput_fifo_enable,pinput_fifo_enable,nfifoempty,pfifoempty, nlast_road,plast_road : std_logic; signal nroad_write,proad_write : std_logic; signal loadin: std_logic; --signals to load the road_data signal nroad_event_count,proad_event_count : unsigned (7 downto 0); signal vroad_event_count : unsigned (7 downto 0); signal nmux_select,pmux_select : std_logic; signal mux_select : std_logic; signal ncentroid, pcentroid : unsigned (12 downto 0); signal vz_centroid_fifo,va_centroid_comp : unsigned (13 downto 0); -- this for temporary assignment of z-centroids and axial centroids signal nz_write,pz_write : std_logic; signal nend_of_event, pend_of_event : std_logic; signal nevent_end,pevent_end : std_logic; signal nrerr,prerr : std_logic; constant zero6 : unsigned (5 downto 0) :="000000"; constant zero13 : unsigned (12 downto 0) := "0000000000000"; constant zero14 : unsigned (13 downto 0) := "00000000000000"; constant zero46 : unsigned (45 downto 0) := "0000000000000000000000000000000000000000000000"; begin ncentroid <= centroid; nend_of_event <= datatype(2); -- the end of event bit is tagged along with the datatype -- and the centroids in the input FIFO -- this process block is used to keep assign a track number -- to the incoming road data process (road_write,plast_road,pcount,pstate,pread_comp,done,pdone,pfifoempty, phits_busy,pz_write) begin -- initialization of the signals ncount <= pcount; nread_comp <= pread_comp; nread_hitreg <= pread_hitreg; nstate <= pstate; ndone <= done; ninput_fifo_enable <= pinput_fifo_enable; nfifoempty <= fifoempty; nroad_write <= road_write; nlast_road <= last_road; nhits_busy <= phits_busy; nroad_event_count <= proad_event_count; vroad_event_count <= "00000000"; nz_write <= pz_write; nevent_end <= pevent_end; case pstate is when sevent => ncount <= zero6; vcount <= zero6; nhits_busy <= '0'; loadin <= '0'; ninput_fifo_enable <= '0'; nz_write <= '0'; nevent_end <= '0'; if(event_start = '1') then -- yes, we have a new event so go to the next state nstate <= sfirstload; nroad_event_count <= proad_event_count + 1; -- the new internal event count else nstate <= sevent; end if; when sfirstload => -- will load the first road into the comparator if (proad_write = '1') then -- do we have a road_write signal only -- then this the first road and there are more to come loadin <= '1'; vcount<= zero6; nstate <= snext; elsif(plast_road = '1') then -- do we have no roads and this is the signal of end of roads nstate <= slast_road; else nstate <= sfirstload; -- otherwise wait in this state for a road_write signal end if; when snext => -- checking whether the road_write signal has gone low, -- only then can we wait for the next road_write high if (proad_write ='0') then nstate <= sload; loadin <= '0'; else nstate <= snext; end if; when sload => --loading the next road_data into next comaparator if (proad_write = '1') then ncount <= pcount + 1; vcount <= pcount + 1; loadin <= '1'; nstate <= snext; elsif (plast_road = '1') then nstate <= slast_road; else nstate <= sload; end if; when slast_road => -- the previous road was the last raod -- so now load the centroid if (pfifoempty = '0') then ninput_fifo_enable <= '1'; nhits_busy <= '1'; vroad_event_count <= proad_event_count - 1; -- storing the current event value nstate <= sdecide; else nstate <= slast_road; end if; when sdecide => ninput_fifo_enable <= '0'; if (datatype(1 downto 0) = "10") then -- if the centroid is axial mux_select <= '0'; nstate <= scomp_read; elsif(datatype(1 downto 0) = "11") then -- if the centroid is z-axis mux_select <= '1'; nstate <= scentroid_write; nz_write <= '1'; else nstate <= slast_road; end if; when scentroid_write => -- this state writes the z-centroid in the block to be formatted -- and written to the fifo nz_write <= '1'; nstate <= slast_road; when scomp_read => -- now the comaparator output is read to be read in the -- hit register to get valid hits nread_comp <= '1'; -- active high signal nstate <= shitreg_read; when shitreg_read => nread_hitreg <= '1'; nread_comp <= '0'; nstate <= swait; when swait => -- wait till the hits for the centroid are found and put in the data format nread_hitreg <= '0'; if (pdone ='1') then -- active high signal from the pointer block if (pfifoempty = '0'and pend_of_event = '1') then -- indicating it is through with the centroids nstate <= sevent; -- yes wait for the new event start nhits_busy <= '0'; -- the hit filter is not busy, the calculation is done elsif (pfifoempty = '1' and pend_of_event = '0') then -- no not yet done, but fifo is still being loaded nstate <= sdata_wait; else nstate <= slast_road; -- go pull another centroid end if; else nstate <= swait; end if; when sdata_wait => -- wait for the fifo to go down again if (pfifoempty = '0') then nstate <= slast_road; else nstate <= sdata_wait; end if; when others => -- if any other state other than the above defined go to the initial state nstate <= sevent; end case; end process; -- this process block is to decide whether axial centroids should go to the comparator -- or the zaxis-degree centroids to the fifo process(pmux_select,pcentroid) begin va_centroid_comp <= zero14; vz_centroid_fifo <= zero14; case mux_select is when '0' => va_centroid_comp <= pend_of_event & pcentroid; when '1' => vz_centroid_fifo <= pend_of_event & pcentroid; when others => va_centroid_comp <= zero14; vz_centroid_fifo <= zero14; end case; end process; --this block assigns the comparator in which road-data will be loaded process(loadin,pcount,proad) variable tcount : unsigned (5 downto 0); begin nroad <= proad; tcount := vcount + 1; if(loadin = '1') then -- active low signal road <= tcount; else road <= zero6; end if; end process; -- this block give is out the final mask to be used to determine the hits process(pread_comp,pmask) variable tmask : unsigned (5 downto 0); begin tmask := pcount + 1; nmask <= pmask; if(pread_comp = '1') then mask <=tmask; else mask <= zero6; end if; end process; -- process block to register the signals process(clock,reset,nstate,ncount,nread_comp,ndone,nfifoempty,nroad_write, nlast_road,nhits_busy,nroad,nmask,nroad_event_count,ncentroid,nevent_end) begin if (reset ='0') then pstate <= sevent; pcount <= zero6; pmask <= zero6; proad <= zero6; pread_comp <= '0'; pread_hitreg <= '0'; pdone <= '0'; pfifoempty <= '0'; proad_write <= '0'; plast_road <= '0'; phits_busy <= '0'; proad_event_count <= "00000000"; pcentroid <= zero13; pevent_end <= '0'; pend_of_event <= '0'; elsif( clock'event and clock='1') then pstate <= nstate; pcount <= ncount; pmask <= nmask; proad <= nroad; pread_comp <= nread_comp; pread_hitreg <= nread_hitreg; pdone <= ndone; pfifoempty <= nfifoempty; proad_write <= nroad_write; plast_road <= nlast_road; phits_busy <= nhits_busy; proad_event_count <= nroad_event_count; pcentroid <= ncentroid; pevent_end <= nevent_end; pend_of_event <= nend_of_event; end if; end process; -- block to register the centroid fifo enable signal process( clock,reset,ninput_fifo_enable,nz_write) begin if (reset ='0') then pinput_fifo_enable <= '0'; pz_write <= '0'; elsif( clock'event and clock='0') then pinput_fifo_enable <= ninput_fifo_enable; pz_write <= nz_write; end if; end process; -- assignment of all output signals read_comp <= pread_comp; read_hitreg <= pread_hitreg; count <= pcount; input_fifo_enable <= pinput_fifo_enable; hits_busy <= phits_busy; road_event_count <= vroad_event_count; a_centroid_comp <= va_centroid_comp; z_centroid_fifo <= vz_centroid_fifo; z_write <= pz_write; end architecture behavior; C.19: Z-CENTROID ------------------------------------------------------------------- --File:z_centroid.vhd -- To put the z centroids in the right format and then give them to L3 -- and also store them in a FIFO within the design -- Originally created by : Shweta Lolage : Date 06/29/2000 -------------------------------------------------------------------- -- The initialization of the standard libraries library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ----------------------------------------------------------------------- -- Entity Declaration entity z_centroid is port (clock,reset : in std_logic; zvc_enable : in std_logic; -- this signal indicates whether the data should be written to the fifo's z_centroid : in unsigned (13 downto 0); -- the z- axis centroid tagged with the end of event on the MSB z_write : in std_logic; -- write signal from the control indicating the centroid coming in -- is z axis-type l3_trailer : in unsigned (31 downto 0); -- this trailer is passed on from the centroid finder block pulse_area : in unsigned (1 downto 0); -- from the centroid finder output FIFO z_l3_output : out unsigned (31 downto 0); -- the output which is passed on to the L3 buffer z_enable : out std_logic ); end entity z_centroid; -- Architecture Body architecture behavior of z_centroid is -- internal signals for the process blocks signal nz_l3_output,pz_l3_output : unsigned (31 downto 0); signal nz_enable,pz_enable : std_logic; signal nl3_trailer,pl3_trailer : unsigned (31 downto 0); signal pevent_status,nevent_status : std_logic; signal pcentroid,ncentroid : unsigned(12 downto 0); signal ppulse_area, npulse_area : unsigned (1 downto 0); constant c_type : unsigned (1 downto 0) := "11"; constant zero2 : unsigned (1 downto 0) := "00"; constant zero4 : unsigned (3 downto 0) := "0000"; constant zero5 : unsigned (4 downto 0) := "00000"; constant zero11 : unsigned (10 downto 0) := "00000000000"; constant zero13 : unsigned (12 downto 0) := "0000000000000"; constant zero14 : unsigned (13 downto 0) := "00000000000000"; constant zero17 : unsigned (16 downto 0) := "00000000000000000"; constant zero32 : unsigned (31 downto 0) := "00000000000000000000000000000000"; begin nl3_trailer <= l3_trailer; nevent_status <= z_centroid(13); ncentroid <= z_centroid (12 downto 0); npulse_area <= pulse_area; process(zvc_enable,z_write) begin nz_l3_output <= pz_l3_output; if (zvc_enable = '1' and z_write = '1') then nz_enable <= '1'; if (pevent_status = '0') then nz_l3_output <= "0" & pl3_trailer(21 downto 19) & c_type & ppulse_area & pl3_trailer(18 downto 8) & pcentroid; else nz_l3_output <= pl3_trailer; end if; else nz_enable <= '0'; end if; end process; -- this process block is to register the signals process( reset,clock,nz_l3_output,nz_enable) begin if(reset ='0') then pz_l3_output <= zero32; pl3_trailer <= zero32; pcentroid <= zero13; ppulse_area <= zero2; pevent_status <= '0'; pz_enable <= '0'; elsif (clock'event and clock ='1') then pz_l3_output <= nz_l3_output; pl3_trailer <= nl3_trailer; pcentroid <= ncentroid; ppulse_area <= npulse_area; pevent_status <= nevent_status; pz_enable <= nz_enable; end if; end process; -- assignment of the output signals z_l3_output <= pz_l3_output; z_enable <= pz_enable; end architecture behavior; C.20: COMPARATOR ------------------------------------------------------------------- --File:comparator.vhd -- To compare the strip pointer with the data value from the -- road data -- Originally created by : Shweta Lolage --Modified by Shweta Lolage on 05/15/2000 : Changes made according to the new approach -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity comparator is port (clock,reset : in std_logic; centroid : in unsigned (10 downto 0); -- the centroid value of out of the centroid finder uroaddata : in unsigned (10 downto 0); -- the upper road_data address lroaddata : in unsigned (10 downto 0); -- the lower road)data address loadroad: in std_logic; -- load the road data at the inputs into the comparator hit : out std_logic -- to give outthe comparator output ); end entity comparator; -- Architecture Body architecture behavior of comparator is -- internal signals for the process blocks signal ndata,pdata, compare1, compare2 : std_logic; signal nroaddatau,proaddatau,nroaddatal,proaddatal : unsigned (10 downto 0); constant zero11 : unsigned ( 10 downto 0) := "00000000000"; begin -- this process block loads in the upper and lower road-data in the comparator process(loadroad,uroaddata,lroaddata) begin if (loadroad = '1') then nroaddatal <= lroaddata; nroaddatau <= uroaddata; else nroaddatal <= proaddatal; nroaddatau <= proaddatau; end if; end process; -- this block is used for the comparison of the road-data -- with the given centroid process(proaddatau,proaddatal,centroid) begin compare1 <= '0'; compare2 <= '0'; if( proaddatau /= zero11 and centroid /= zero11 ) then if (proaddatau >= centroid ) then compare1 <= '1'; else compare1 <= '0'; end if; else compare1 <= '0'; end if; if(proaddatal /= zero11 and centroid /= zero11) then if (proaddatal <= centroid) then compare2 <= '1'; else compare2 <= '0'; end if; else compare2 <= '0'; end if; end process; -- this block gives the result of the comparison process (compare1,compare2) begin ndata <= pdata; if (compare1 ='1' and compare2 ='1') then ndata <= '1'; else ndata <= '0'; end if; end process; -- the process block to register the road-data signals process( nroaddatau,nroaddatal,ndata,clock,reset) begin if ( reset ='0') then proaddatau <= zero11; proaddatal <= zero11; pdata <= '0'; elsif ( clock'event and clock='1') then proaddatau <= nroaddatau; proaddatal <= nroaddatal; pdata <= ndata; end if; end process; -- final out from the comparator hit <= pdata; end architecture behavior; C.21: HIT REGISTER ------------------------------------------------------------------- -- File:r2_hitreg_v2.vhd -- this process block finds the valid hits -- Originally created by : Shweta Lolage -- By Shweta Lolage on 05/17/2000 : Changes made according to the new approach --modified on 06/04 /2000 : by Shweta Lolage -- modified to remove the delays -- The control output line removed from this block and put in the control logic as an additional state -- date - 09/04/2000 - Shweta Lolage -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity hitreg is port (clock, reset : in std_logic; read_comp : in std_logic; -- read signal from the control block mask,hitreg : in unsigned (45 downto 0); -- the mask register and the hit register used to find the valid hits hitbit : out std_logic_vector (45 downto 0) -- valid hits ); end entity hitreg; -- Architecture Body architecture behavior of hitreg is signal nhitbit, phitbit : std_logic_vector (45 downto 0); constant zero46 : std_logic_vector (45 downto 0) := "0000000000000000000000000000000000000000000000"; begin -- process block to register in the mask and the hits register process (mask,hitreg) begin if (read_comp = '1') then nhitbit(0) <= mask(0) and hitreg(0); nhitbit(1) <= mask(1) and hitreg(1); nhitbit(2) <= mask(2) and hitreg(2); nhitbit(3) <= mask(3) and hitreg(3); nhitbit(4) <= mask(4) and hitreg(4); nhitbit(5) <= mask(5) and hitreg(5); nhitbit(6) <= mask(6) and hitreg(6); nhitbit(7) <= mask(7) and hitreg(7); nhitbit(8) <= mask(8) and hitreg(8); nhitbit(9) <= mask(9) and hitreg(9); nhitbit(10) <= mask(10) and hitreg(10); nhitbit(11) <= mask(11) and hitreg(11); nhitbit(12) <= mask(12) and hitreg(12); nhitbit(13) <= mask(13) and hitreg(13); nhitbit(14) <= mask(14) and hitreg(14); nhitbit(15) <= mask(15) and hitreg(15); nhitbit(16) <= mask(16) and hitreg(16); nhitbit(17) <= mask(17) and hitreg(17); nhitbit(18) <= mask(18) and hitreg(18); nhitbit(19) <= mask(19) and hitreg(19); nhitbit(20) <= mask(20) and hitreg(20); nhitbit(21) <= mask(21) and hitreg(21); nhitbit(22) <= mask(22) and hitreg(22); nhitbit(23) <= mask(23) and hitreg(23); nhitbit(24) <= mask(24) and hitreg(24); nhitbit(25) <= mask(25) and hitreg(25); nhitbit(26) <= mask(26) and hitreg(26); nhitbit(27) <= mask(27) and hitreg(27); nhitbit(28) <= mask(28) and hitreg(28); nhitbit(29) <= mask(29) and hitreg(29); nhitbit(30) <= mask(30) and hitreg(30); nhitbit(31) <= mask(31) and hitreg(31); nhitbit(32) <= mask(32) and hitreg(32); nhitbit(33) <= mask(33) and hitreg(33); nhitbit(34) <= mask(34) and hitreg(34); nhitbit(35) <= mask(35) and hitreg(35); nhitbit(36) <= mask(36) and hitreg(36); nhitbit(37) <= mask(37) and hitreg(37); nhitbit(38) <= mask(38) and hitreg(38); nhitbit(39) <= mask(39) and hitreg(39); nhitbit(40) <= mask(40) and hitreg(40); nhitbit(41) <= mask(41) and hitreg(41); nhitbit(42) <= mask(42) and hitreg(42); nhitbit(43) <= mask(43) and hitreg(43); nhitbit(44) <= mask(44) and hitreg(44); nhitbit(45) <= mask(45) and hitreg(45); else nhitbit <= zero46; end if; end process; -- process block to register the signals process(clock,reset,nhitbit) begin if ( reset = '0') then phitbit <= zero46; elsif ( clock'event and clock ='1') then phitbit <= nhitbit; end if; end process; -- assigning the outputs hitbit <= phitbit; end architecture; C.22: HIT FORMAT ------------------------------------------------------------------- -- File:hit_format.vhd -- Process block to locate the hits from the valid hits register -- and give them to the format block to put them in the data format -- Originally created by : Shweta Lolage -- By Shweta Lolage on 05/17/2000 : Changes made according to the new approach -- Changes are made to the design to combine the hit block and the format block -- date : 09/04/2000 - Shweta Lolage -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity hit_format is port (clock,reset : in std_logic; count : in unsigned (5 downto 0); -- upper limit for the hit search as this is the number of comparators -- loaded with valid road_data hitreg: in std_logic_vector (45 downto 0); -- valid hits register l3_trailer : in unsigned (31 downto 0) ; -- this trailer is passed on from the centroid finder block pulsearea : in unsigned (1 downto 0); -- pulse_area for the centroid centroid : in unsigned (13 downto 0); -- centroid which is compared hitreg_valid : in std_logic; -- read valid hit register signal cen_done,hits_done : out std_logic; --cen_done signal for the channel control block output : out unsigned (32 downto 0); -- the final output to the hits FIFO fifo_enable,end_of_event : out std_logic -- signal to the main control block indicating that the -- -- channel has valid hits ); end entity hit_format; -- Architecture Body architecture behavior of hit_format is type hitstates is (sinit,spoint_select,sready,sread_hits,sread_bit,swrite_hit, soutput_hit,snext_hit,strailer); signal pstate,nstate : hitstates; signal or1,or2,or3,or4,or5 : std_logic; signal nor1,nor2,nor3,nor4,nor5 : std_logic; signal por1,por2,por3,por4,por5 : std_logic; signal nhits_present,phits_present,pcen_done,ncen_done : std_logic; signal npointer,ppointer: unsigned (5 downto 0); signal ncounter,pcounter: unsigned (5 downto 0); signal nhitreg_valid,phitreg_valid : std_logic; signal nhitreg, phitreg : std_logic_vector(45 downto 0); signal nhits_done,phits_done,nbit,pbit : std_logic; constant zero46 : std_logic_vector (45 downto 0) := "0000000000000000000000000000000000000000000000"; signal ndata,pdata: unsigned (32 downto 0); signal ncount,pcount : unsigned (5 downto 0); signal noutput,poutput : unsigned (32 downto 0); signal nfifoenable,pfifoenable : std_logic; signal npulsearea,ppulsearea : unsigned (1 downto 0); signal pcentroid, ncentroid : unsigned (12 downto 0); signal nevent_status, pevent_status : std_logic; signal nl3_trailer,pl3_trailer : unsigned (31 downto 0); constant zero33 : unsigned (32 downto 0) := "000000000000000000000000000000000"; constant zero32 : unsigned (31 downto 0) := "00000000000000000000000000000000"; constant zero22 : unsigned (21 downto 0) := "0000000000000000000000"; constant zero17 : unsigned (16 downto 0) := "00000000000000000"; constant zero16 : unsigned (15 downto 0) := "0000000000000000"; constant zero11 : unsigned (10 downto 0) := "00000000000"; constant zero8 : unsigned (7 downto 0) := "00000000"; constant zero6 : unsigned (5 downto 0) := "000000"; constant zero3 : unsigned (2 downto 0) := "000"; constant two : unsigned (1 downto 0) := "10"; constant three : unsigned (1 downto 0) := "11"; begin -- the initialization of the signals npulsearea <= pulsearea; ncentroid <= centroid(12 downto 0); nevent_status <= centroid(13); -- the bit tagged along with centroid indicating the end of event nl3_trailer <= l3_trailer; nhitreg_valid <= hitreg_valid; -- this process block groups the comparators to reduce the search process(hitreg) variable tor1,tor2,tor3,tor4,tor5 : std_logic; begin tor1 := '0'; tor2 := '0'; tor3 := '0'; tor4 := '0'; tor5 := '0'; for i in 0 to 9 loop tor1 := tor1 or hitreg(i); end loop; or1 <= tor1; for i in 10 to 19 loop tor2 := tor2 or hitreg(i); end loop; or2 <= tor2; for i in 20 to 29 loop tor3 := tor3 or hitreg(i); end loop; or3 <= tor3; for i in 30 to 39 loop tor4 := tor4 or hitreg(i); end loop; or4 <= tor4; for i in 40 to 45 loop tor5 := tor5 or hitreg(i); end loop; or5 <= tor5; end process; -- this process block is to find the hits and send them to the format block process(ppointer,hitreg_valid,count,pcen_done,pcen_done,pcounter) begin ncen_done <= pcen_done; ncounter <= pcounter; nor1 <= por1; nor2 <= por2; nor3 <= por3; nor4 <= por4; nor5 <= por5; nhits_present <= phits_present; npointer <= ppointer; nhitreg <= phitreg; nfifoenable <= pfifoenable; noutput <= poutput; nhits_done <= phits_done; case pstate is when sinit => -- initial state, ncen_done <= '0'; nhits_present <= '0'; nfifoenable <= '0'; nhits_done <= '0'; if (hitreg_valid ='1') then -- is valid register ready to be read nstate <= spoint_select; -- yes, go ahead and select the point of start -- after determining whether we have any hits nhitreg <= hitreg; nor1 <= or1; nor2 <= or2; nor3 <= or3; nor4 <= or4; nor5 <= or5; else nstate <= sinit; -- no be in this state and wait for it nhitreg <= zero46; nor1 <='0'; nor2 <='0'; nor3 <='0'; nor4 <='0'; nor5 <='0'; end if; when spoint_select => nfifoenable <= '0'; nhits_present <= por1 or por2 or por3 or por4 or por5; if (por1 ='1') then npointer <= "000000"; else if (por2 ='1') then npointer <= "001010"; else if (por3 ='1') then npointer <= "010100"; else if (por4='1') then npointer <= "011110"; else if (por5 = '1') then npointer <= "101000"; else npointer <= "000000"; end if; end if; end if; end if; end if; nstate <= sready; when sready => -- read the valid hits nfifoenable <= '0'; if (phits_present = '1') then -- are there any hits in this register nstate <= sread_hits; -- yes there are ncen_done <= '0'; ncounter <= ppointer; else ncen_done <= '1'; nstate <= sinit; end if; when sread_hits => nstate <= sread_bit; nfifoenable <= '0'; case pcounter is when "000000" => nbit <= phitreg(0); when "000001" => nbit <= phitreg(1); when "000010" => nbit <= phitreg(2); when "000011" => nbit <= phitreg(3); when "000100" => nbit <= phitreg(4); when "000101" => nbit <= phitreg(5); when "000110" => nbit <= phitreg(6); when "000111" => nbit <= phitreg(7); when "001000" => nbit <= phitreg(8); when "001001" => nbit <= phitreg(9); when "001010" => nbit <= phitreg(10); when "001011" => nbit <= phitreg(11); when "001100" => nbit <= phitreg(12); when "001101" => nbit <= phitreg(13); when "001110" => nbit <= phitreg(14); when "001111" => nbit <= phitreg(15); when "010000" => nbit <= phitreg(16); when "010001" => nbit <= phitreg(17); when "010010" => nbit <= phitreg(18); when "010011" => nbit <= phitreg(19); when "010100" => nbit <= phitreg(20); when "010101" => nbit <= phitreg(21); when "010110" => nbit <= phitreg(22); when "010111" => nbit <= phitreg(23); when "011000" => nbit <= phitreg(24); when "011001" => nbit <= phitreg(25); when "011010" => nbit <= phitreg(26); when "011011" => nbit <= phitreg(27); when "011100" => nbit <= phitreg(28); when "011101" => nbit <= phitreg(29); when "011110" => nbit <= phitreg(30); when "011111" => nbit <= phitreg(31); when "100000" => nbit <= phitreg(32); when "100001" => nbit <= phitreg(33); when "100010" => nbit <= phitreg(34); when "100011" => nbit <= phitreg(35); when "100100" => nbit <= phitreg(36); when "100101" => nbit <= phitreg(37); when "100110" => nbit <= phitreg(38); when "100111" => nbit <= phitreg(39); when "101000" => nbit <= phitreg(40); when "101001" => nbit <= phitreg(41); when "101010" => nbit <= phitreg(42); when "101011" => nbit <= phitreg(43); when "101100" => nbit <= phitreg(44); when "101101" => nbit <= phitreg(45); when others => nbit <= '0'; end case; when sread_bit => nfifoenable <= '0'; if (pbit = '1') then -- no there are more nstate <= swrite_hit; ncount <= pcounter; else nstate <= snext_hit; ncount <= pcount; end if; when swrite_hit => nstate <= soutput_hit; nfifoenable <= '0'; ndata(32) <= '0'; ndata(31 downto 26) <= pcount; ndata(25 downto 24) <= ppulsearea; ndata(23 downto 13) <= pl3_trailer(18 downto 8); ndata(12 downto 0) <= pcentroid; when soutput_hit => nstate <= snext_hit; noutput<= pdata; nfifoenable <= '1'; when snext_hit => -- state to decide whether we should go ahead for the next hit nfifoenable <= '0'; if (pcounter <= count) then -- have we reached the end of the comparators ncen_done <='0'; ncounter <= pcounter + 1; -- No , the end has not yet come nstate <= sread_hits; else ncen_done <= '1'; ncounter <= "000000"; if (pevent_status = '0')then nstate <= sinit; -- yes go to start and wait for the next lot else nstate <= strailer; nhits_done <= '1'; ndata (32) <= '1'; ndata(31 downto 0) <= pl3_trailer; end if; end if; when strailer => nstate <= sinit; nfifoenable <= '1'; noutput <= pdata; nhits_done <= '0'; when others => -- any other state other than the once defined above, go to the initial state nstate <= sinit; ncen_done <= '0'; nhits_done <= '0'; end case; end process; --this process block registers the signals process(clock,reset) begin if (reset ='0') then ppointer <="000000"; pcounter <="000000"; phits_present <= '0'; pstate <= sinit; pcen_done <= '0'; pbit <= '0'; phitreg_valid <= '0'; por1 <= '0'; por2 <= '0'; por3 <= '0'; por4 <= '0'; por5 <= '0'; phitreg <= zero46; elsif (clock'event and clock ='1') then ppointer <= npointer; pcounter <= ncounter; phits_present <= nhits_present; pstate <= nstate; pcen_done <= ncen_done; pbit <= nbit; phitreg_valid <= nhitreg_valid; por1 <= nor1; por2 <= nor2; por3 <= nor3; por4 <= nor4; por5 <= nor5; phitreg <= nhitreg; end if; end process; -- the process block to register the signals process(clock,reset) begin if(reset ='0') then poutput <= zero33; pcount <= zero6; pdata <= zero33; ppulsearea <= "00"; pcentroid <= "0000000000000"; pevent_status <= '0'; pl3_trailer <= zero32; pfifoenable <= '0'; phits_done <= '0'; elsif( clock'event and clock='1') then poutput <= noutput; pcount <= ncount; pdata <= ndata; ppulsearea <= npulsearea; pcentroid <= ncentroid; pl3_trailer <= nl3_trailer; pevent_status <= nevent_status; pfifoenable <= nfifoenable; phits_done <= nhits_done; end if; end process; -- final out to the fifo, this block is not totally complete as will have to see the handshaking with the fifo output <= poutput; fifo_enable <= pfifoenable; end_of_event <= poutput(32); cen_done <= pcen_done; hits_done <= phits_done; end architecture; C.23: HIT READ OUT ------------------------------------------------------------------- -- File:hit_readout.vhd -- Process block to read the hits from the FIFO by the control block -- Originally created by : Shweta Lolage :08/01/2000 -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity hit_readout is port (clock, reset : in std_logic; hits_enable,hit_fifo_empty, hits_busy : in std_logic; read_hit_fifo,hits_available : out std_logic ); end entity hit_readout; -- Architecture Body architecture behavior of hit_readout is signal nread_hit_fifo,pread_hit_fifo : std_logic; begin process( hits_enable, hit_fifo_empty) begin if(hits_enable = '1' and hit_fifo_empty = '0') then nread_hit_fifo <= '1'; -- this is read_req signal to the fifo else nread_hit_fifo <= '0'; end if; end process; hits_available <= hits_busy; -- this is an internal signal to the read_out control to indicate that hits are being processed reg : process ( clock, reset) begin if(reset = '0') then pread_hit_fifo <= '0'; elsif (clock'event and clock ='1') then pread_hit_fifo <= nread_hit_fifo; end if; end process reg; -- assigning the outputs read_hit_fifo <= pread_hit_fifo; end architecture; C.24: TRAILER PATTERN RECOGINSER ------------------------------------------------------------------- -- File:trailer_pat.vhd -- Process block to check for the trailer -- Originally created by : Shweta Lolage :08/01/2000 -------------------------------------------------------------------- library altera; use altera.maxplus2.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; -- Entity Declaration entity trailer_pat is port (stream : in unsigned(4 downto 0); trailer_signal : out std_logic ); end entity trailer_pat; -- Architecture Body architecture behavior of trailer_pat is constant pattern : unsigned (4 downto 0):= "11110"; begin with stream select trailer_signal <= '1' when pattern, '0' when others; end architecture; C.25 DETAILED MEMORY ALLOCATION OF THE DOWNLOADED PARAMETERS 1. Monitor space: 1K memory: 0000 – 03FF. 2. Miscellaneous: 1K memory: 0400 – 07FF. 3. Gain Offset LUT: 4K X 8: 0800 – 17FF 4. Test data LUT: 1K (default) X 18: 1800 – 1BFF. 5. Empty Space: 1C00 – 3FFF. 6. Road data LUT: 16 K X 22: 4000 – 7FFF. C.25.1 The monitoring data memory allocation 1. SERR,mismatch,SMT_ID,SEQ_ID,HDI_ID,data (last data word read): address 0000. 2. SERR error count : address 0001. 3. Mismatch counter: mismatch in the SEQ-ID or the HDI-ID: address 0002. 4. Zero error count: Zero byte not found: address 0003. 5. Number of undefined data_type clusters: address 0010. 6. Number of axial data_type clusters: address 0011. 7. Number of stereo data_type clusters: address 0012. 8. Number of Z-axis data_type clusters: address 0013. 9. Data activity on Chip(I): address 0020-0028. C.25.2 The miscellaneous memory space memory allocation 1. Bad channel: 32 X 64: address: 0400 – 047F. 2. Chip ranges: 24 X 1: address: 0480. 3. Pulse area thresholds: 24 X 4 X4: address: 0500 – 0503. 4. Miscellaneous parameters: 32 X 1: address: 0580. 5. Cluster threshold values: 17 X 4: address: 0600 – 0603. 77