conv_dyn_burst_ctrl.vhd 11.3 KB
Newer Older
1 2 3
--==============================================================================
-- CERN (BE-CO-HT)
-- Burst mode control module
4
-- Copyright CERN 2017
5 6 7 8 9 10 11 12
--==============================================================================
--
-- author: Denia Bouhired (denia.bouhired@cern.ch)
--
-- Date of creation: 19-09-2016 
--
-- version: 1.0
--
13
-- Description:
14
-- This module serves as a burst mode controller. When pulses of  
15
-- pre-defined length (250 ns or 1.2us) arrive, depending on the frequency, the 
16 17
-- module will allow the pulse to go through for a pre-defined amount of
-- time, before going into pulse rejection mode. The rejection lasts for
18 19 20 21 22 23 24 25 26
-- the time it takes for the "temperature" to reach the upper limit
-- g_max_temp. For each frequency, the time of failure selected
-- corresponds to the time it takes to reach g_max_temp for pulses of a given 
-- frequency. 
-- The array of values representing the thermal properties at the pulse level 
-- is given as the array of integers temp_decre_step. This array of values is 
-- generated in pre-processing via python script (*link to be added*). These 
-- values correspond to the thermal model of the board components. They are 	
-- different for short 250ns pulses and long 1.2us pulses.
27 28 29 30

-- Any modification to the board specification which would change the 
-- high frequency operation behaviour, would require changing the 3
-- parameters g_1_pulse_temp_rise, g_max_temp and t_temp_decre_step. These 
31
-- are generated using the Python file (*link to be added*). 
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

-- dependencies:
--    

--==============================================================================
-- GNU LESSER GENERAL PUBLIC LICENSE
--==============================================================================
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--==============================================================================
50 51


52 53 54 55 56 57 58 59
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.conv_common_gw_pkg.all;

60 61 62
----------------------------------------------------------------------------
-- ENTITY DECLARATION
----------------------------------------------------------------------------
63 64 65 66

entity conv_dyn_burst_ctrl is
	generic
	(
67 68 69 70 71 72 73 74
		-- Fixed pulse width
		g_pwidth 			: natural range 2 to 40 	:= 5;
		-- Array of decrement values derived from the choses thermal model
		-- The following t_temp_decre_step values correspond to "1s, 6.5s, 10s, 26s, 
		-- 36.66s and continuous" for pulsing for frequencies 
		-- 2MHz, 1.33MHz, 1MHz, 800kHz, 667 kHz and 571kHz respectively.
		g_temp_decre_step 	: t_temp_decre_step 		:=
						(0,0, 769, 31, 104, 14, 82, 0 ,0, 0, 0, 0, 0, 0, 0, 0);
75
		
76 77
		--Scaled temperature rise resulting from a single pulse.
		g_1_pulse_temp_rise	:in unsigned (19 downto 0)	:= x"01388"; --5000
78
		
79 80
		-- Scaled maximum temperature ceiling for pulse inhibition 
		g_max_temp			:in unsigned (39 downto 0) 	:= x"02540BE400" --10^10
81 82 83 84
	);
	port
	(
    -- Clock and active-low reset inputs
85 86
		clk_i        		: in  std_logic;
		rst_n_i      		: in  std_logic;
87

88
	-- Enable input, high frequency repetition is enabled when '1'
89
		en_i         	 	: in  std_logic;
90
	
91
	-- Asynchronous input pulse with rising and falling edges
92 93 94
		pulse_burst_i 		: in std_logic;
		pulse_r_edge_p_i	: in std_logic;
		pulse_f_edge_p_i	: in std_logic;
95
	
96 97
	-- Temp_rise is output for external probing
		temp_rise_o			: out unsigned (39 downto 0) ;
98 99
	-- Dynamic temperature-controlled ouput pulse train.
		pulse_burst_o		: out std_logic;
100
	
101
	-- Burst error output, pulses high for one clock cycle when a pulse arrives
102
	-- within a burst rejection phase
103
		burst_err_p_o : out std_logic	
104 105 106
	);
	end entity conv_dyn_burst_ctrl;
	
107
----------------------------------------------------------------------------
108
-- ARCHITECTURE
109
----------------------------------------------------------------------------
110 111 112
	architecture behav of conv_dyn_burst_ctrl is
	
	
113 114 115 116 117
	type t_state is (
		IDLE,			
		PULSE_REPEAT,	
		PULSE_REJECT	
	);
118

119 120 121
	signal burst_ctrl_rst			: std_logic;
	signal temp_rise				: unsigned (39 downto 0) ;
	signal single_cycle_cnt			: integer;
122 123 124
	signal n_cycle_cnt				: integer range 1 to g_temp_decre_step'LENGTH;
	signal thermal_array_lgth :natural := 7;
	signal thermal_res : natural; -- thermal resolution in clock cycles
125
	
126 127
	signal state                     : t_state;
	signal nxt_state			     : t_state;
128
	signal s_pulse_reject, s_pulse_repeat : std_logic;
129
	
130
	begin
131
	
132 133
		thermal_array_lgth <= 7 when g_pwidth = 5 else 16;
		thermal_res <= g_pwidth; --Resolution depends on i/p pulse width
134
	
135 136 137
	-- Output from module depends on burst_ctrl_rst and en_i
	---------------------------------------------------------
		pulse_burst_o <= '0' when burst_ctrl_rst = '1' else pulse_burst_i and en_i;
138
		temp_rise_o <= temp_rise;
139
-----------------------------------------------------------------------------
140
-- Finite State Machine FSM
141 142 143 144
-----------------------------------------------------------------------------
-- Finite State Machine to control pulse repetition as a function of rising 
-- board temperature. The FSM relies on temp_rise counter for state transitions
-----------------------------------------------------------------------------
145
  
146 147
-- Process to trigger state transitions
----------------------------------------
148 149 150 151 152 153 154 155 156 157 158
  p_fsm_transitions: process(clk_i)
  begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        state 						<= IDLE;
      elsif (en_i = '1') then
		state	 					<= nxt_state;
      end if;
    end if;
  end process;
  
159 160 161
  
-- Process to define FSM states
--------------------------------
162 163
  p_thermal_fsm_states : process (state, pulse_r_edge_p_i, pulse_f_edge_p_i, 
												n_cycle_cnt, temp_rise, en_i )
164 165 166
  begin
	case state is 
	
167 168 169
	-------------------------------------------------------------------------
	-- The FSM is IDLE, when the board is reset
	-------------------------------------------------------------------------
170
		when IDLE =>
171
			if en_i = '1' and pulse_r_edge_p_i = '1' then
172
					nxt_state 	<= PULSE_REPEAT;
173
			else
174
					nxt_state 	<= IDLE; 
175
			end if;
176 177
		
	-------------------------------------------------------------------------
178 179 180
	-- PULSE_REPEAT pulses are repeated as long as the temperature is below 
	-- maximum g_max_temp.
	-- While the temperature counter temp_rise is above 0, the time between 
181 182
	-- 2 pulses is used to decrement it, i.e. to cool down.
	-------------------------------------------------------------------------
183
		when PULSE_REPEAT =>
184
			if temp_rise <= g_max_temp then
185 186
					nxt_state <= PULSE_REPEAT;
			else
187
					nxt_state <= PULSE_REJECT;
188 189
			end if;
			
190
	-----------------------------------------------oo-----------------------
191 192 193
	-- PULSE_REJECT applies when a new pulse causes temperature to exceed 
	-- maximum value
	-- i.e. temp_rise >= g_max_temp.
194
	------------------------------------------------------------------------
195
		when PULSE_REJECT =>
196 197
			if (pulse_f_edge_p_i = '1' and temp_rise <= g_max_temp) OR 
				temp_rise = 0 then
198
				nxt_state <= PULSE_REPEAT;
199 200 201
			else
				nxt_state <= PULSE_REJECT;
			end if;
202 203 204 205
		
		when others =>
            nxt_state <= IDLE;
			
206 207 208
	end case;
			
	end process p_thermal_fsm_states;
209 210 211 212


-- Process to define FSM outputs
--------------------------------
213 214 215 216 217 218
	p_thermal_fsm_outputs : process (state, pulse_r_edge_p_i)
  begin	 
	-------------------------------------------------------------------------
	-- In the idle state all outputs are reset
	-------------------------------------------------------------------------
	case state is 
219 220
			
			when IDLE =>
221 222 223 224
				burst_ctrl_rst <= '0';
				burst_err_p_o  <= '0';
				s_pulse_reject <= '0';
				s_pulse_repeat <= '0';
225

226 227 228 229
	--------------------------------------------------------------------------
	-- In PULSE_REPEAT pulses the input pulse is copied to the output and 
	-- the state flag s_pulse_repeat is set
	--------------------------------------------------------------------------
230
			when PULSE_REPEAT =>
231 232 233 234
				burst_err_p_o  <= '0';
				burst_ctrl_rst <= '0';
				s_pulse_repeat <= '1';
				s_pulse_reject <= '0';
235

236 237 238 239
	---------------------------------------------------------------------------
	-- PULSE_REJECT sets burst_ctrl_rst to 1 to cutoff the output and sets the 
	-- error pulse
	---------------------------------------------------------------------------
240 241
			
			when PULSE_REJECT =>
242 243 244 245 246 247 248 249 250 251 252 253
				burst_err_p_o  <= pulse_r_edge_p_i;
				burst_ctrl_rst <= '1';
				s_pulse_reject <= '1';
				s_pulse_repeat <= '0';
		
			when others =>
				burst_ctrl_rst <= '0';
				burst_err_p_o  <= '0';
				s_pulse_reject <= '0';
				s_pulse_repeat <= '0';
	end case;
	
254 255
	end process p_thermal_fsm_outputs;

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
	-- Process to count in n clk cycles steps
	-- single_cycle_cnt counts clock cycles. When it reaches the thermal resolution
	-- (pulse width dependent) it increments  n_cycle_cnt by 1 and single_cycle_cnt
	-- is reset to 1 again. n_cycle_cnt is reset to 1 only when a new pulse arrives
	-- and pulse output inhibition is not active.
	---------------------------------------------------------------------------
	p_n_cycle_cnt : process(clk_i)
	begin
	if rising_edge(clk_i) then
		if rst_n_i = '0' then
				single_cycle_cnt <= 1;
				n_cycle_cnt   <= 1;
		else
			-- Reset counters in the event of a new pulse only 
			-- when pulse rejection is not active
271 272
			if (pulse_r_edge_p_i = '1' and burst_ctrl_rst = '0') then --OR
			 --(pulse_f_edge_p_i = '1' and n_cycle_cnt /= 1) then
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
				single_cycle_cnt <= 1;
				n_cycle_cnt   <= 1;
			else
				--count clk cycles 
				single_cycle_cnt <= single_cycle_cnt + 1;
				if single_cycle_cnt = thermal_res then
					if n_cycle_cnt < thermal_array_lgth then
					-- increment every n=thermal_res clk cycles
						n_cycle_cnt <= n_cycle_cnt + 1;
					end if;
						single_cycle_cnt <= 1;
				end if;
			end if;
		end if;
	end if;
  end process p_n_cycle_cnt;
  	
	-- Process to output temperature rise. When a new pulse arrives, 
	-- temp_rise rises at the falling edge. Between pulses, temp_rise is 
	-- decremented according to the thermal model. 
	------------------------------------------------------------------------------
	p_temp_rise : process(clk_i)
	begin
	if rising_edge(clk_i) then
		if rst_n_i = '0' then
				temp_rise <=  (others => '0');
		else
			if s_pulse_repeat = '1' then
				if pulse_f_edge_p_i ='1' then
					temp_rise <= temp_rise + g_1_pulse_temp_rise;
				else
					if temp_rise >= g_temp_decre_step(n_cycle_cnt-1) then
						temp_rise <= temp_rise - to_unsigned(g_temp_decre_step(n_cycle_cnt-1), 40);
					else
						temp_rise <= (others => '0');
					end if;
				end if;
			elsif s_pulse_reject = '1' and temp_rise > 0 then
311 312 313 314 315
				if temp_rise >= g_temp_decre_step(n_cycle_cnt-1) then
					temp_rise <= temp_rise - to_unsigned(g_temp_decre_step(n_cycle_cnt-1), 40);
				else
					temp_rise <= (others => '0');
				end if;
316 317 318 319 320 321 322
			end if;
		end if;
	end if;
  end process p_temp_rise;


  
323
	end architecture behav;