Commit 3695b894 authored by Denia Bouhired-Ferrag's avatar Denia Bouhired-Ferrag

Now using an FSM to hadel pulse repetition and rejection. Thermal model constant…

Now using an FSM to hadel pulse repetition and rejection. Thermal model constant decrement steps are now a generic rather than a signal
parent dbc8bae9
......@@ -9,9 +9,12 @@
--
-- version: 1.0
--
-- description:
-- This module serves as a burst mode controller. When pulses of pre-defined length (250 ns) arrive, this module evaluates whether the module needs some "cool-off" time every burst_length number of pulses. Burst-length is the maximum number of pulses the board can handle at maximum frequency 2MHz and is determined through direct laboratory measurements on board prototypes. It is considered a pure hardware limitation. For version 1 this is set to absolute maximum of 1000 but the generic value can be changed for lower values.
-- Description:
-- This module serves as a burst mode controller. When pulses of pre-defined length (250 ns) arrive, depending on the frequency, the 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 the time it takes for the "temperature" to go below the set 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 at the same frequency. This is mapped onto the temperature rise caused by a single pulse (the maximum rise at 2MHz max frequency is g_1_pulse_temp_rise) of the corresponding period. 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??). These values correspond to the thermal model of the board components defined at the pulse level.
-- 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 are generated using the Python file (link?)
-- dependencies:
--
......@@ -31,6 +34,8 @@
-- last changes:
-- 19-09-2016 Denia Bouhired File created.
-- 11-01-2017 Denia Bouhired Small modifications to improve code.
-- 15-01-2017 Denia Bouhired Now using 2 FSMs for states and outputs.
-- 23-01-2017 Denia Bouhired Changed temp_decrement_step from signal to generic, to allow module to run for different width pulses.
--==============================================================================
-- TODO: -
--==============================================================================
......@@ -40,7 +45,6 @@ use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.conv_common_gw_pkg.all;
......@@ -49,30 +53,30 @@ entity conv_dyn_burst_ctrl is
generic
(
-- Fixed pulse width set to 5 clock cycles = 5* 50ns = 250 ns
g_pwidth : natural range 2 to 40 := 5;
-- Scaled temperature rise resulting from single pulse. This number can be defined empirically or derived from temperature measurements on the board.
g_1_pulse_temp_rise :in unsigned (19 downto 0) := x"0A410";
g_pwidth : natural range 2 to 40 := 5;
g_temp_decre_step : t_temp_decre_step := (0, 769, 31, 104, 14, 82, 0 ,0, 0, 0, 0, 0, 0, 0, 0);
--Scaled temperature rise resulting from single pulse.
g_1_pulse_temp_rise :in unsigned (19 downto 0) := x"01388";--5000
-- Scaled maximum temperature ceiling before pulse inhibition is necessary to lower temperature
--g_max_temp :in unsigned (39 downto 0) := x"174876E800"
g_max_temp :in unsigned (39 downto 0) := x"00000186A0"--100000
g_max_temp :in unsigned (39 downto 0) := x"02540BE400" --10^10
);
port
(
-- Clock and active-low reset inputs
clk_i : in std_logic;
rst_n_i : in std_logic;
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Enable input, pulse generation is enabled when '1'
-- Enable input, high frequency repetition is enabled when '1'
en_i : in std_logic;
--Input pulse burst or pulse train
-- Input pulse
pulse_burst_i : in std_logic;
--Dynamically controlled ouput pulse train.
pulse_burst_o : out std_logic;
-- output used for debugging. OUGHT TO BE DELETED
temp_rise_c : out unsigned (39 downto 0) ;
-- Burst error output, pulses high for one clock cycle when a pulse arrives
-- within a burst rejection phase
burst_err_p_o : out std_logic
......@@ -82,156 +86,240 @@ entity conv_dyn_burst_ctrl is
architecture behav of conv_dyn_burst_ctrl is
type t_temp_decre is array (0 to 6) of integer;
--type t_temp_decre_step is array (0 to 5) of integer;
--============================================================================
-- Function and procedure declarations
type t_state is (
IDLE,
PULSE_REPEAT,
PULSE_REJECT
);
--============================================================================
-- Function and procedure declarations: Function used if/when mode is extended to work for 1.2us pulse
--============================================================================
function f_temp_resolution (pwidth : natural) return natural is
function f_th_array_lgth (pwidth : natural) return natural is
begin
if pwidth = 5 then --250ns wide pulses
return 5;
return 6;
else
return 24; --1.2us wide pulses
return 15; --1.2us wide pulses
end if;
end function f_temp_resolution;
end function f_th_array_lgth;
--============================================================================
-- Signal declarations
--============================================================================
signal temp_decre : t_temp_decre := (0, 0, 769, 31, 104, 14, 82);
--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.
--signal temp_decre_step : t_temp_decre_step := (0, 769, 31, 104, 14, 82);
signal burst_ctrl_rst : std_logic;
signal pulse_train_in : std_logic;
signal temp_rise : unsigned (39 downto 0) ;
signal test : integer ;
signal test : integer ;
signal temp_fall : unsigned (39 downto 0) ;
signal single_cycle_cnt : integer;
signal n_cycle_cnt : integer;
signal pulse_train_in_d0 : std_logic;
signal pulse_train_in_r_edge_p : std_logic;
signal pulse_train_in_f_edge_p : std_logic;
signal n_cycle_cnt : integer;
signal pulse_train_in_d0 : std_logic;
signal pulse_train_in_r_edge_p : std_logic;
signal pulse_train_in_f_edge_p : std_logic;
constant thermal_res : natural := f_temp_resolution (g_pwidth); -- thermal resolution in clock cycles
signal state : t_state;
signal nxt_state : t_state;
constant thermal_res : natural := g_pwidth; -- thermal resolution in clock cycles
constant thermal_array_lgth :natural := f_th_array_lgth (g_pwidth);
begin
-- Generate the pulse on rising edge of pulse_burst_i
p_pulse_redge: process (burst_ctrl_rst, pulse_burst_i)
begin
--if rising_edge(clk_i) then
--TO DOooo consider moving within else statement
-- Generate the pulse on rising edge of pulse_burst_i
p_pulse_redge: process (burst_ctrl_rst, pulse_burst_i)
begin
if (burst_ctrl_rst = '1') then
if falling_edge(pulse_burst_i) then --pulse_burst_i) then -- wait for pulse to finish before cutoff
--TODO why not use falling edge 1-clk-cycle pulse
if falling_edge(pulse_burst_i) then -- wait for pulse to finish before cutoff
pulse_train_in <= '0';
end if;
elsif (en_i = '1') then
pulse_train_in <= pulse_burst_i; --re-activate output only if input line is off
end if;
--end if;
--end if;
end process p_pulse_redge;
end process p_pulse_redge;
pulse_burst_o <= pulse_train_in; --copy controlled input burst to output
temp_rise_c <= temp_rise; --TODO to delete as output is not really necessary
pulse_burst_o <= pulse_train_in; --copy controlled input burst to output
-- TODO is it necessary since pulse should already be synchronised to clock domain?/
p_pulse_redge_detect : process (clk_i) is
begin
if rising_edge(clk_i) then
if (rst_n_i = '0') then
pulse_train_in_d0 <= '0';
pulse_train_in_r_edge_p <= '0';
elsif (en_i='1') then
pulse_train_in_d0 <= pulse_burst_i;
pulse_train_in_r_edge_p <= pulse_burst_i and (not pulse_train_in_d0);
pulse_train_in_f_edge_p <= (not pulse_burst_i) and pulse_train_in_d0;
end if;
end if;
end process p_pulse_redge_detect;
--Synchronize the trigger in clk_i domain
p_pulse_redge_detect : process (clk_i) is
begin
if rising_edge(clk_i) then
if (rst_n_i = '0') then
pulse_train_in_d0 <= '0';
pulse_train_in_r_edge_p <= '0';
elsif (en_i='1') then
pulse_train_in_d0 <= pulse_burst_i;
pulse_train_in_r_edge_p <= pulse_burst_i and (not pulse_train_in_d0);
pulse_train_in_f_edge_p <= (not pulse_burst_i) and pulse_train_in_d0;
end if;
end if;
end process p_pulse_redge_detect;
p_n_cycle_cnt : process(clk_i)
begin
if rising_edge(clk_i) then
--Process to count in n clk cycles steps
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
if pulse_train_in_r_edge_p = '1' then --and burst_ctrl_rst = '0' then
--reset counters in the event of a new pulse
single_cycle_cnt <= 1;
n_cycle_cnt <= 1;
elsif pulse_train_in = '0' then --TODO change condition of if statement, try with falling edge
single_cycle_cnt <= single_cycle_cnt+1;
elsif (en_i = '1') then
--reset counters in the event of a new pulse only when pulse rejection is not activ
if pulse_train_in_r_edge_p = '1' and burst_ctrl_rst = '0' then
single_cycle_cnt <= 1;
n_cycle_cnt <= 1;
--When no pulse is being repeated, wither because pulse is off or because it is being rejected
elsif pulse_train_in = '0' then
single_cycle_cnt <= single_cycle_cnt + 1; --count clk cycles
if single_cycle_cnt = thermal_res then
if n_cycle_cnt < 7 then
n_cycle_cnt <= n_cycle_cnt + 1;
if n_cycle_cnt < thermal_array_lgth then
n_cycle_cnt <= n_cycle_cnt + 1; --increment every n=thermal_res clk cycles
end if;
single_cycle_cnt <= 1;
--temp_fall <= to_unsigned(temp_decre(n_cycle_cnt), 40);
end if;
end if;
end if;
end if;
end if;
end process p_n_cycle_cnt;
-- Process to implement FSM transitions
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;
-- FInite State Machine to control pulse repetition as a function of rising board temperature.
-- The FSM uses a temp_rise counter
p_thermal_fsm_states : process (state, pulse_train_in_r_edge_p, pulse_train_in_f_edge_p, temp_rise, n_cycle_cnt )
begin
case state is
-----------------------------------------------------------------------------------------
-- The FSM is IDLE, when the board is completely "cool", temp_rise =0, and no
-- new pulses arrive after 1.75us from the last one
-----------------------------------------------------------------------------------------
when IDLE =>
if pulse_train_in_r_edge_p = '1' then
if temp_rise >= 0 and temp_rise <= g_max_temp then
nxt_state <= PULSE_REPEAT;
else
nxt_state <= PULSE_REJECT;
end if;
end if;
-----------------------------------------------------------------------------------------
-- 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 2 pulses is used to decrement it.
-----------------------------------------------------------------------------------------
when PULSE_REPEAT =>
if temp_rise >= 0 and temp_rise <= g_max_temp then
if pulse_train_in_r_edge_p = '1' then
nxt_state <= PULSE_REPEAT;
elsif temp_rise = 0 and n_cycle_cnt = 6 then--and temp_rise <= g_max_temp then
nxt_state <= IDLE;
end if;
else
nxt_state <= PULSE_REJECT;
end if;
-----------------------------------------------------------------------------------------
-- PULSE_REJECT applies when a new pulse causes temperature to exceed maximum value
--i.e. temp_rise >= g_max_temp.
-----------------------------------------------------------------------------------------
when PULSE_REJECT =>
if temp_rise <= g_max_temp then
if pulse_train_in_f_edge_p ='1' then
nxt_state <= PULSE_REPEAT;
end if;
else
nxt_state <= PULSE_REJECT;
end if;
p_thermal_sim : process (clk_i)
end case;
end process p_thermal_fsm_states;
p_thermal_fsm_outputs : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
temp_rise <= (others => '0');
burst_ctrl_rst <= '1';
burst_err_p_o <= '0';
else
if (temp_rise) >= 0 and ((temp_rise) <= (g_max_temp)) then
burst_err_p_o <= '0';
if pulse_train_in_f_edge_p = '1' then --wait until pulse finishes before repetition
burst_ctrl_rst <= '0';
-----------------------------------------------------------------------------------------
-- The FSM is IDLE, when the board is completely "cool", temp_rise =0, and no
-- new pulses arrive after 1.75us from the last one
-----------------------------------------------------------------------------------------
case state is
when IDLE =>
temp_rise <= (others => '0');
burst_ctrl_rst <= '0';
burst_err_p_o <= '0';
-----------------------------------------------------------------------------------------
-- 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 2 pulses is used to decrement it.
-----------------------------------------------------------------------------------------
when PULSE_REPEAT =>
elsif pulse_train_in_r_edge_p = '1' then --new pulse
if burst_ctrl_rst = '1' then
burst_err_p_o <= '1';
--end if;
--if burst_ctrl_rst = '0' then -- temperature less than maximum
else
burst_ctrl_rst <= '0';
if temp_rise >= 0 and temp_rise <= g_max_temp then
if pulse_train_in_f_edge_p = '1' then
temp_rise <= temp_rise + g_1_pulse_temp_rise;
--else ;
end if;
--burst_err_p_o <= '0';
--elsif signed(temp_rise) /= 0 and pulse_train_in = '0' then
elsif (temp_rise) /= 0 then --and pulse_burst_i = '0' then --temperature fall between pulses
test <= temp_decre(n_cycle_cnt-1);
if temp_rise > temp_decre(n_cycle_cnt-1) then
temp_rise <= temp_rise - to_unsigned(temp_decre(n_cycle_cnt-1), 40);
elsif temp_rise /=0 and pulse_train_in_r_edge_p /= '1'then
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;
else
burst_ctrl_rst <= '1';
burst_err_p_o <= '0';
if pulse_train_in_r_edge_p = '1' then
burst_err_p_o <= '1';
end if;
end if;
--elsif (signed(temp_rise) > signed(g_max_temp)) and pulse_train_in = '0' then -- and
elsif ((temp_rise) > (g_max_temp)) then -- and pulse_burst_i = '0' then -- and (pulse_train_in_f_edge_p = '1') then
burst_ctrl_rst <= '1';
burst_err_p_o <= '0';
if pulse_train_in_r_edge_p = '1' then
burst_err_p_o <= '1';
end if;
temp_rise <= temp_rise - temp_decre(n_cycle_cnt-1);
end if;
end if;
end if;
end process p_thermal_sim;
-----------------------------------------------------------------------------------------
-- PULSE_REJECT applies when a new pulse causes temperature to exceed maximum value
--i.e. temp_rise >= g_max_temp.
-----------------------------------------------------------------------------------------
when PULSE_REJECT =>
burst_ctrl_rst <= '1';
burst_err_p_o <= '0';
if pulse_train_in_r_edge_p = '1' then
burst_err_p_o <= '1';
end if;
temp_rise <= temp_rise - g_temp_decre_step(n_cycle_cnt-1);
end case;
end if;
end process p_thermal_fsm_outputs;
end architecture behav;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment