Skip to content
Snippets Groups Projects
Select Git revision
  • ad1d9b920a12faa97c5a12c6228082f1fa37a14e
  • develop default
  • master protected
3 results

saml-request.model.ts

Blame
  • uart_xstep_timer.vhd 15.31 KiB
    ----------------------------------------------------------------------------------
    --
    -- Project : ModNEF
    -- Component name : uart_xstep
    -- Depencies : uart_controller
    --
    -- Authors : Aurelie Saulquin
    -- Email : aurelie.saulquin@univ-lille.fr
    --
    -- Version : 1.0
    -- Version comment : stable version 
    --
    -- Licenses : cern-ohl-s-2.0
    --
    -- Description : 
    -- UART component where one data transmission(read/write) is use for multiple
    -- emulation step. The first data read from uart controller is the number of data 
    -- 
    ----------------------------------------------------------------------------------
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    use work.math.all;
    
    entity Uart_XStep_Timer is
      generic(
        clk_freq          : integer := 100_000_000;
        baud_rate         : integer := 115_200;
    
        queue_read_depth  : integer := 32;
        queue_read_width  : integer := 1;
    
        queue_write_depth : integer := 32;
    
        input_layer_size  : integer := 8;
        output_layer_size : integer := 8
      );
      port (
        i_clk             : in  std_logic;
        i_en              : in  std_logic;
    
        i_tx              : in  std_logic;
        o_rx              : out std_logic;
    
        i_emu_ready       : in  std_logic;
        o_start_emu       : out std_logic;
        o_reset_membrane  : out std_logic;
    
        i_req             : in  std_logic;
        o_ack             : out std_logic;
        i_emu_busy        : in  std_logic;
        i_spike_flag      : in  std_logic;
        i_aer             : in  std_logic_vector(log_b(output_layer_size, 2)-1 downto 0);
    
        o_req             : out std_logic;
        i_ack             : in  std_logic;
        o_emu_busy        : out std_logic;
        o_spike_flag      : out std_logic;
        o_aer             : out std_logic_vector(log_b(input_layer_size, 2)-1 downto 0)
      );
    end Uart_XStep_Timer;
    
    architecture Behavioral of Uart_XStep_Timer is
    
      component uart_controller is
        generic(
          clk_freq          : integer := 100_000_000;
          baud_rate         : integer := 115_200;
          oversamp_rate     : integer := 16;
          
          queue_read_depth  : integer := 64;
          queue_read_width  : integer := 1;
          queue_read_type   : string  := "fifo";
    
          queue_write_depth : integer := 16;
          queue_write_width : integer := 1;
          queue_write_type  : string := "fifo"   -- fifo or lifo
        );
        port(
          i_clk                 : in  std_logic;
          i_en                  : in  std_logic;
          o_busy                : out std_logic;
          o_reset_detected      : out std_logic;
    
          -- UART pins
          i_tx                  : in  std_logic;
          o_rx                  : out std_logic;
          o_uart_busy           : out std_logic;       
          
          -- read I/O
          o_read_data           : out std_logic_vector(queue_read_width*8-1 downto 0);
          i_read_pop            : in  std_logic;
          o_read_busy           : out std_logic;
          o_read_queue_empty    : out std_logic;
          o_read_queue_full     : out std_logic;
    
          -- write I/O
          i_start_transmission  : in  std_logic;
          i_write_data          : in  std_logic_vector(queue_write_width*8-1 downto 0);
          i_write_push          : in  std_logic;
          o_write_busy          : out std_logic;
          o_write_queue_empty   : out std_logic;
          o_write_queue_full    : out std_logic     
        );
      end component;
    
      -- type definition
      type emu_state_t              is (idle, wait_data, check_emu, emulate, wait_out_aer, send_aer, wait_transmission, push_timer, push_timer_2, start_tr);
      type uart_to_network_state_t  is (idle, check_data, get_data_number, request, accept, transfert);
      type network_to_uart_state_t  is (idle, wait_request, accept, wait_aer, push_data_number);
      
      -- queue constant
      constant queue_write_width  : integer := log_b(output_layer_size, 256);
    
      -- read queue signals
      signal read_data  : std_logic_vector(queue_read_width*8-1 downto 0) := (others=>'0');
      signal read_pop   : std_logic := '0';
      signal read_busy  : std_logic;
      signal read_empty : std_logic;
    
      -- write queue signals
      signal write_data       : std_logic_vector(queue_write_width*8-1 downto 0) := (others=>'0');
      signal write_aer_buffer : std_logic_vector(queue_write_width*8-1 downto 0) := (others=>'0');
      signal write_push       : std_logic := '0';
      signal write_busy       : std_logic;
      signal write_empty      : std_logic;
    
      -- UART signals
      signal start_uart_transmission : std_logic := '0';
    
      -- emulation signals
      signal emu_state : emu_state_t := idle;
      signal start_emu : std_logic;
    
      -- uart to network signals
      signal uart_to_network_state : uart_to_network_state_t := idle; 
      signal uart_to_network_busy : std_logic := '0';
    
      -- network to uart signals
      signal network_to_uart_data_number : std_logic_vector(queue_write_width*8-1 downto 0) := (others=>'0');
      signal network_to_uart_state : network_to_uart_state_t := idle;
      signal network_to_uart_busy : std_logic := '0';
    
      -- membrane reset signals
      signal reset_detected       : std_logic := '0';
      signal reset_membrane       : std_logic := '0';
    
      -- timer signals
      constant timer_width        : integer := 2;
      signal   timer              : std_logic_vector(timer_width*8-1 downto 0) := (others=>'0');
      signal   count_time         : std_logic := '0';
      signal   reset_timer        : std_logic := '0';
      signal   timer_data         : std_logic_vector(queue_write_width*8-1 downto 0) := (others=>'0');
      signal   timer_byte_counter : integer := 0;
      --constant z : std_logic_vector(queue_write_width*8-1-7 downto 0) := (others=>'0');
    
    begin
    
      o_start_emu <= start_emu;
      o_reset_membrane <= reset_membrane;
    
      process(i_clk)
      begin
        if rising_edge(i_clk) then
          if count_time = '1' then
            timer <= std_logic_vector(unsigned(timer)+1);
          elsif reset_timer='1' then
            timer <= (others=>'0');
          end if;
        end if;
      end process;
      
      -- controller FSM
      process(i_clk, i_en)
      begin
        if i_en = '0' then
          emu_state <= idle;
          start_emu <= '0';
          start_uart_transmission <= '0';
        else
          if rising_edge(i_clk) then
            case emu_state is
              when idle => 
                start_emu <= '0';
                start_uart_transmission <= '0';
                reset_membrane <= '0';
                reset_timer <= '1';
                count_time <= '0';
                timer_byte_counter <= 0;
                if read_busy = '1' then
                  emu_state <= wait_data;
                else
                  emu_state <= idle;
                end if;
    
              when wait_data =>
                reset_timer <= '0';
                if read_busy = '0' then
                  emu_state <= check_emu;
                else
                  emu_state <= wait_data;
                end if;
    
              when check_emu =>
                if i_emu_ready = '1' then
                  emu_state <= emulate;
                  start_emu <= '1';
                  count_time <= '1';
                else
                  emu_state <= check_emu;
                end if;
    
              when emulate =>
                start_emu <= '0';
                if network_to_uart_busy = '1' then
                  emu_state <= wait_out_aer;
                else
                  emu_state <= emulate;
                end if;
    
              when wait_out_aer =>
                if i_emu_ready = '1' and network_to_uart_busy='0' then
                  count_time <= '0';
                  if read_empty = '1' then -- no more data to process
                    emu_state <= push_timer;
                    --timer_data(7 downto 0) <= timer(7 downto 0);
                    reset_membrane <= reset_detected;
                  else
                    emu_state <= check_emu;
                  end if;
                else
                  emu_state <= wait_out_aer;
                end if;
    
              when push_timer =>
                --timer_data(7 downto 0) <= timer(7 downto 0);
                emu_state <= push_timer_2;
    
              when push_timer_2 =>
                --timer_data(7 downto 0) <= timer(15 downto 8);
                emu_state <= start_tr;
    
              when start_tr =>
                start_uart_transmission <= '1';
                emu_state <= send_aer;
    
              when send_aer =>
                start_uart_transmission <= '0';
                reset_membrane <= '0';
                if  write_busy = '1' then
                  emu_state <= wait_transmission;
                  
                else
                  emu_state <= send_aer;
                end if;
    
              when wait_transmission =>
                reset_membrane <= '0';
                if write_busy = '0' then
                  emu_state <= idle;
                else
                  emu_state <= wait_transmission;
                end if;
            end case;
          end if;
        end if;
      end process;
    
      -- Controller to network FSM
      --o_aer <= read_data(log_b(input_layer_size, 2)-1 downto 0) when uart_to_network_state = transfert else (others=>'0');
      process(i_clk, i_en)
        variable data_counter                 : integer range 0 to queue_read_depth := 0;
        variable uart_to_network_data_number  : integer range 0 to queue_read_depth := 0;
      begin
        if rising_edge(i_clk) then
          if i_en = '0' then
            o_req <= '0';
            o_spike_flag <= '0';
            o_emu_busy <= '0';
            read_pop <= '0';
            uart_to_network_busy <= '0';
            uart_to_network_state <= idle;
          else
            case uart_to_network_state is
              when idle =>
                o_req <= '0';
                o_spike_flag <= '0';
                read_pop <= '0';
                if start_emu = '1' then
                  uart_to_network_state <= check_data;
                  o_emu_busy <= '1';
                  uart_to_network_busy <= '1';
                else
                  uart_to_network_state <= idle;
                  o_emu_busy <= '0';
                  uart_to_network_busy <= '0';
                end if;
    
                when check_data =>
                  if read_empty = '1' then
                    uart_to_network_state <= idle;
                    o_emu_busy <= '0';
                    uart_to_network_busy <= '0';
                  else
                    uart_to_network_state <= get_data_number;
                    read_pop <= '1';
                  end if;
    
                when get_data_number =>
                  uart_to_network_state <= transfert;
                  read_pop <= '0';
                  data_counter := 0;
                  uart_to_network_data_number := to_integer(unsigned(read_data));
                  
    
                  if uart_to_network_data_number = 0 then
                    uart_to_network_busy <= '0';
                    uart_to_network_state <= idle;
                  else
                    uart_to_network_state <= request;
                    o_req <= '1';
                  end if;
    
                when request =>
                  if i_ack = '1' then
                    uart_to_network_state <= accept;
                    o_req <= '0';
                  else
                    uart_to_network_state <= request;
                    o_req <= '1';
                  end if;
    
                when accept =>
                  if i_ack = '0' then
                    uart_to_network_state <= transfert;
                    read_pop <= '1';
                  else
                    uart_to_network_state <= accept;
                  end if;
    
                when transfert =>
                  if data_counter = uart_to_network_data_number then
                    uart_to_network_state <= idle;
                    o_emu_busy <= '0';
                    read_pop <= '0';
                    o_spike_flag <= '0';
                    uart_to_network_busy <= '0';
                  elsif data_counter = uart_to_network_data_number-1 then
                    read_pop <= '0';
                    uart_to_network_state <= transfert;
                    o_spike_flag <= '1';
                    data_counter := data_counter+1;
                    o_aer <= read_data(log_b(input_layer_size, 2)-1 downto 0);
                  else
                    uart_to_network_state <= transfert;
                    read_pop <= '1';
                    o_spike_flag <= '1';
                    data_counter := data_counter + 1;
                    o_aer <= read_data(log_b(input_layer_size, 2)-1 downto 0);
                  end if;
            end case;
          end if;
        end if;
      end process;
    
      write_aer_buffer(log_b(output_layer_size, 2)-1 downto 0) <= i_aer;
      timer_data <= timer(7 downto 0) when emu_state=push_timer else
                    timer(15 downto 8) when emu_state = push_timer_2 else
                    (others=>'0');
      write_data <= write_aer_buffer when network_to_uart_state = wait_aer else 
                    network_to_uart_data_number when network_to_uart_state = push_data_number else
                    timer_data when emu_state=push_timer else
                    timer_data when emu_state = push_timer_2 else
                    (others=>'0');
    
      write_push <= i_spike_flag when network_to_uart_state = wait_aer else 
                    '1' when network_to_uart_state = push_data_number else
                    '1' when emu_state = push_timer else
                    '1' when emu_state = push_timer_2 else
                    '0';
      process(i_clk, i_en)
        variable data_counter : integer range 0 to output_layer_size := 0;
      begin
        if rising_edge(i_clk) then
          if i_en = '0' then
            network_to_uart_state <= idle;
            network_to_uart_busy <= '0';
            o_ack <= '0';
            data_counter := 0;
          else
            case network_to_uart_state is
              when idle =>
                data_counter := 0;
                o_ack <= '0';
                if i_emu_busy = '1' then
                  network_to_uart_state <= wait_request;
                  network_to_uart_busy <= '1';
                else
                  network_to_uart_state <= idle;
                  network_to_uart_busy <= '0';
                end if;
    
              when wait_request =>
                if i_emu_busy = '0' then
                  network_to_uart_state <= push_data_number;
                  network_to_uart_data_number <= std_logic_vector(to_unsigned(data_counter, queue_write_width*8));
                elsif i_req = '1' then
                  o_ack <= '1';
                  network_to_uart_state <= accept;
                else
                  network_to_uart_state <= wait_request;
                end if;
    
              when accept =>
                if i_req = '0' then
                  network_to_uart_state <= wait_aer;
                  o_ack <= '0';
                else
                  network_to_uart_state <= accept;
                  o_ack <= '1';
                end if;
    
              when wait_aer => 
                if i_emu_busy = '0' then
                  network_to_uart_state <= push_data_number; 
                  network_to_uart_data_number <= std_logic_vector(to_unsigned(data_counter, queue_write_width*8));
                else 
                  network_to_uart_state <= wait_aer;
                  if i_spike_flag = '1' then
                    data_counter := data_counter + 1;
                  end if;
                end if;
    
              when push_data_number =>
                network_to_uart_state <= idle;
                network_to_uart_busy <= '0';
            end case;
          end if;
        end if;
      end process;
    
    
      c_uart_controller : uart_controller generic map(
        clk_freq => clk_freq,
        baud_rate => baud_rate,
        oversamp_rate => 16,
    
        queue_read_depth => queue_read_depth,
        queue_read_width => queue_read_width,
        queue_read_type => "fifo",
    
        queue_write_depth => queue_write_depth,
        queue_write_width => queue_write_width,
        queue_write_type => "lifo"
      ) port map(
        i_clk => i_clk,
        i_en => i_en,
        o_busy => open,
        o_reset_detected => reset_detected,
        i_tx => i_tx,
        o_rx => o_rx,
        o_uart_busy => open,
        o_read_data => read_data,
        i_read_pop => read_pop,
        o_read_busy => read_busy,
        o_read_queue_empty => read_empty,
        o_read_queue_full => open,
        i_start_transmission => start_uart_transmission,
        i_write_data => write_data,
        i_write_push => write_push,
        o_write_busy => write_busy,
        o_write_queue_empty => open,
        o_write_queue_full => open
      );
    
    end Behavioral;