eFEX firmware  1.7.3
ATLAS l1-calo - electron and tau feature extraction firmware for eFEX boards

Back to eFEX documentation
ufc_controller.vhd
Go to the documentation of this file.
1 
8 
9 
11 library IEEE;
12 use IEEE.STD_LOGIC_1164.ALL;
13 use IEEE.NUMERIC_STD.ALL;
14 
16 entity ufc_controller is
17  generic (
18  TX_DATA_WIDTH : integer := 64;
19  GAP_WIDTH : integer := 11 -- width of gap counter ex; 5 makes gap of 32 cycles
20  );
21  Port (
22  clock : in STD_LOGIC;
23  reset : in STD_LOGIC;
24  enable : in STD_LOGIC;
25  busy_tob : in STD_LOGIC_VECTOR(3 DOWNTO 0);
26  busy_raw : in STD_LOGIC_VECTOR(3 DOWNTO 0);
27  s_axi_tx_tready : in STD_LOGIC;
28  s_axi_ufc_tx_tready : in STD_LOGIC;
29  s_axi_ufc_tx_tvalid : out STD_LOGIC;
30  s_axi_ufc_tx_tdata : out STD_LOGIC_VECTOR(2 DOWNTO 0);
31  AXI_UFC_TDATA : out STD_LOGIC_VECTOR((TX_DATA_WIDTH-1) DOWNTO 0)
32  );
33 end ufc_controller;
34 
36 architecture RTL of ufc_controller is
37 
38  signal gap_limit : unsigned(GAP_WIDTH-1 DOWNTO 0);
39  signal gap_count : unsigned(GAP_WIDTH-1 DOWNTO 0);
40  signal s_axi_ufc_tx_tvalid_i, enable_reg, reset_reg : std_logic :='0';
41  signal message : STD_LOGIC_VECTOR(7 DOWNTO 0);
42  signal busy_tob_reg, busy_tob_last, busy_raw_reg, busy_raw_last : STD_LOGIC_VECTOR(3 DOWNTO 0);
43  signal state : std_logic_vector(1 downto 0) := "00";
44  signal send_message : std_logic :='0';
45 
46  attribute ASYNC_REG : string;
47  attribute ASYNC_REG of busy_tob_reg : signal is "TRUE";
48  attribute ASYNC_REG of busy_raw_reg : signal is "TRUE";
49  attribute ASYNC_REG of busy_tob_last : signal is "TRUE";
50  attribute ASYNC_REG of busy_raw_last : signal is "TRUE";
51 
52 begin
53 gap_limit <= (others => '1');
54 
55 register_reg_block: process (clock) begin
56  if rising_edge (clock) then
57  busy_tob_reg <= busy_tob;
58  busy_raw_reg <= busy_raw;
59  end if;
60 end process register_reg_block;
61 
62 register_last_block: process (clock) begin
63  if rising_edge (clock) then
64  busy_tob_last <= busy_tob_reg;
65  busy_raw_last <= busy_raw_reg;
66  end if;
67 end process register_last_block;
68 
69 control_reg_block: process (clock) begin
70  if rising_edge (clock) then
71  enable_reg <= enable;
72  reset_reg <= reset;
73  end if;
74 end process control_reg_block;
75 
76 s_axi_ufc_tx_tdata <= "000"; -- 2 byte message
77 
78 gap_counter: process (clock) begin
79  if rising_edge (clock) then
80  if (reset_reg = '1') or (state = "10") then
81  gap_count <= (others => '0');
82  elsif (gap_count /= gap_limit) then
83  gap_count <= gap_count+1;
84  else
85  gap_count <= gap_count;
86  end if;
87  end if;
88 end process gap_counter;
89 
90 time_to_send: process (clock) begin
91  if rising_edge (clock) then
92  if (reset_reg = '1') or (state = "10") then
93  send_message <= '0';
94  elsif (gap_count = gap_limit) or (busy_tob_reg /= busy_tob_last) or (busy_raw_reg /= busy_raw_last) then
95  send_message <= '1';
96  end if;
97  end if;
98 end process time_to_send;
99 
100 send_ufc: process (clock) begin
101  if rising_edge (clock) then
102  if (reset_reg = '1') or (enable_reg = '0') then
103  s_axi_ufc_tx_tvalid_i <= '0';
104  state <= "00";
105  elsif (send_message = '1') and (s_axi_tx_tready = '1') and (s_axi_ufc_tx_tready = '0') and ((state = "00") or (state = "01")) then
106  s_axi_ufc_tx_tvalid_i <= '1'; --begin arbitration
107  state <= "01";
108  elsif (send_message = '1') and (s_axi_ufc_tx_tvalid_i = '1') and (s_axi_ufc_tx_tready = '1') and (state = "01") then
109  s_axi_ufc_tx_tvalid_i <= '0'; --arbitration complete
110  state <= "10";
111  elsif (state = "10") then
112  state <= "00";
113  else
114  s_axi_ufc_tx_tvalid_i <= '0'; --error
115  end if;
116  end if;
117 end process send_ufc;
118 
119 s_axi_ufc_tx_tvalid <= s_axi_ufc_tx_tvalid_i;
120 
121 UFC_Message: process (clock)
122  variable busy_source: STD_LOGIC_VECTOR(3 DOWNTO 0);
123  variable tob_busy, raw_busy, parity_low, parity_high: std_logic;
124  Begin
125  if rising_edge (clock) then
126  if (busy_tob_last /= "0000") then
127  tob_busy := '1';
128  else
129  tob_busy := '0';
130  end if;
131  if (busy_raw_last /= "0000") then
132  raw_busy := '1';
133  else
134  raw_busy := '0';
135  end if;
136  busy_source := busy_tob_last or busy_raw_last;
137  parity_low := not(busy_source(0) xor raw_busy xor tob_busy);
138  parity_high := not(busy_source(3) xor busy_source(2) xor busy_source(1));
139  message <= parity_high & busy_source(3 downto 1) & parity_low & busy_source(0) & raw_busy & tob_busy;
140  end if;
141 end process UFC_Message;
142 
143 AXI_UFC_TDATA(15 DOWNTO 0) <= message & message;
144 AXI_UFC_TDATA((TX_DATA_WIDTH-1) downto 16) <= (others => '0');
145 
146 end RTL;
UFC_block...