207 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
-------------------------------------------------------------------------------
 | 
						|
-- Title      : MachXO2 Serial Configuration
 | 
						|
-- Project    : tiny-xo2
 | 
						|
-------------------------------------------------------------------------------
 | 
						|
-- File       : top.vhd
 | 
						|
-- Author     : Mario Hüttel  <mario.huettel@gmx.net>
 | 
						|
-- Company    : 
 | 
						|
-- Created    : 2017-11-21
 | 
						|
-- Last update: 2017-11-23
 | 
						|
-- Platform   : 
 | 
						|
-- Standard   : VHDL'93/02
 | 
						|
-------------------------------------------------------------------------------
 | 
						|
-- Description: 
 | 
						|
-------------------------------------------------------------------------------
 | 
						|
-- Copyright (c) 2017 GPLv2
 | 
						|
-------------------------------------------------------------------------------
 | 
						|
-------------------------------------------------------------------------------
 | 
						|
 | 
						|
library ieee;
 | 
						|
use ieee.std_logic_1164.all;
 | 
						|
use ieee.numeric_std.all;
 | 
						|
 | 
						|
entity config_top is
 | 
						|
 | 
						|
  generic (
 | 
						|
    CLKDIV : integer := 10);
 | 
						|
 | 
						|
  port (
 | 
						|
    clk     : in  std_logic;            -- input clock 12 MHz
 | 
						|
    dts     : in  std_logic;            -- DTS Strobe signal
 | 
						|
    rst_out : out std_logic;
 | 
						|
    uart_tx : out std_logic;            -- UART TX
 | 
						|
    uart_rx : in  std_logic);           -- UART RX
 | 
						|
 | 
						|
end entity config_top;
 | 
						|
 | 
						|
 | 
						|
architecture RTL of config_top is
 | 
						|
  type fsm_state_t is (IDLE, CMD, EXEC, REPLY, HANG);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  ----------------- RESET LOGIC ------------------------------
 | 
						|
  signal dts_sync       : std_logic_vector(2 downto 0) := (others => '0');
 | 
						|
  signal rst            : std_logic;    -- reset (high active)
 | 
						|
  ----------------- UART RX ----------------------------------
 | 
						|
  signal data_rx        : std_logic_vector(7 downto 0);
 | 
						|
  signal byte_ready_rx  : std_logic;
 | 
						|
  signal error_rx       : std_logic;
 | 
						|
  ----------------- UART TX ----------------------------------
 | 
						|
  signal data_tx        : std_logic_vector(7 downto 0);
 | 
						|
  signal byte_ready_tx  : std_logic;
 | 
						|
  signal busy_tx        : std_logic;
 | 
						|
  signal config_busy    : std_logic                    := '1';  -- indicates that the core is in configuration/waiting mode
 | 
						|
  -- and the user logic has to stay in reset
 | 
						|
  signal config_active  : std_logic                    := '1';  -- configuration FSM active
 | 
						|
  ---------------------------- Wishbone Bus -------------------------------------
 | 
						|
  signal wb_cyc         : std_logic;
 | 
						|
  signal wb_stb         : std_logic;
 | 
						|
  signal wb_we          : std_logic;
 | 
						|
  signal wb_adr         : std_logic_vector(7 downto 0);
 | 
						|
  signal wb_dat_in      : std_logic_vector(7 downto 0);
 | 
						|
  signal wb_dat_out     : std_logic_vector(7 downto 0);
 | 
						|
  signal wb_ack         : std_logic;
 | 
						|
  -------------------------------- State machine -----------------------------------
 | 
						|
  signal state          : fsm_state_t;
 | 
						|
  signal reply_is_error : std_logic;
 | 
						|
  signal bytecounter    : integer range 0 to 3         := 0;
 | 
						|
 | 
						|
begin  -- architecture RTL
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  -----------------------------------------------------------------------------
 | 
						|
  ------------------------------ Wishbone EFB for Config ----------------------
 | 
						|
  -----------------------------------------------------------------------------
 | 
						|
  efb_ufr_1 : entity work.efb_ufr
 | 
						|
    port map (
 | 
						|
      wb_clk_i    => clk,
 | 
						|
      wb_rst_i    => rst,
 | 
						|
      wb_cyc_i    => wb_cyc,
 | 
						|
      wb_stb_i    => wb_stb,
 | 
						|
      wb_we_i     => wb_we,
 | 
						|
      wb_adr_i    => wb_adr,
 | 
						|
      wb_dat_i    => wb_dat_in,
 | 
						|
      wb_dat_o    => wb_dat_out,
 | 
						|
      wb_ack_o    => wb_ack,
 | 
						|
      wbc_ufm_irq => open);
 | 
						|
 | 
						|
  uart_rx_1 : entity work.uart_rx
 | 
						|
    port map (
 | 
						|
      clk          => clk,
 | 
						|
      rst          => rst,
 | 
						|
      data         => data_rx,
 | 
						|
      byte_ready   => byte_ready_rx,
 | 
						|
      error        => error_rx,
 | 
						|
      ckDiv        => CLKDIV,
 | 
						|
      parityEnable => '1',
 | 
						|
      parityOdd    => '0',
 | 
						|
      twoStopBits  => '0',
 | 
						|
      rx           => uart_rx);
 | 
						|
 | 
						|
  uart_tx_1 : entity work.uart_tx
 | 
						|
    port map (
 | 
						|
      clk          => clk,
 | 
						|
      rst          => rst,
 | 
						|
      data         => data_tx,
 | 
						|
      byte_ready   => byte_ready_tx,
 | 
						|
      busy         => busy_tx,
 | 
						|
      ckDiv        => CLKDIV,
 | 
						|
      parityEnable => '1',
 | 
						|
      parityOdd    => '0',
 | 
						|
      twoStopBits  => '0',
 | 
						|
      tx           => uart_tx);
 | 
						|
 | 
						|
 | 
						|
  -- set config_busy on reset and wait 0.25s. If FSM is not active
 | 
						|
  -- deassert config_busy
 | 
						|
  timeout_counter_busy_gen : process(clk, rst) is
 | 
						|
    variable cnt : integer range 0 to 3000000 := 3000000;  -- 0.25 sec counter
 | 
						|
  begin
 | 
						|
    if rst = '1' then
 | 
						|
      cnt         := 3000000;
 | 
						|
      config_busy <= '1';
 | 
						|
    elsif rising_edge(clk) then
 | 
						|
      config_busy <= '1';
 | 
						|
      if cnt /= 0 then
 | 
						|
        cnt := cnt - 1
 | 
						|
      else
 | 
						|
        if config_active = '0' then
 | 
						|
          config_busy <= '0';
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
    end if;
 | 
						|
  end process timeout_counter_busy_gen;
 | 
						|
 | 
						|
 | 
						|
  -- Generate reset pulse on rising edge of dts input
 | 
						|
  reset_gen : process(clk) is
 | 
						|
  begin
 | 
						|
    if rising_edge(clk) then
 | 
						|
      rst      <= '0';
 | 
						|
      dts_sync <= dts_sync(1 downto 0) & dts;  -- Shif register (sync and edge detect)
 | 
						|
      if (dts_sync(2 downto 1) = "01") then    -- rising edge of DTS
 | 
						|
        rst <= '1';
 | 
						|
      end if;
 | 
						|
    end if;
 | 
						|
  end process reset_gen;
 | 
						|
 | 
						|
 | 
						|
  -- hold user logic in reset until config finished or timeout
 | 
						|
  user_logic_reset_gen : process(clk, rst) is
 | 
						|
  begin
 | 
						|
    if rst = '1' then
 | 
						|
      rst_out <= '1';
 | 
						|
    elsif rising_edge(clk) then
 | 
						|
      if config_busy = '0' then
 | 
						|
        rst_out <= '0';
 | 
						|
      end if;
 | 
						|
    end if;
 | 
						|
  end process user_logic_reset_gen;
 | 
						|
 | 
						|
 | 
						|
  controlFSM : process (clk, rst) is
 | 
						|
  begin  -- process controlFSM
 | 
						|
    if rst = '1' then
 | 
						|
      state          <= IDLE;
 | 
						|
      config_active  <= '0';
 | 
						|
      bytecounter    <= 0;
 | 
						|
      reply_is_error <= '0';
 | 
						|
      -- Wishbone
 | 
						|
      wb_cyc         <= '0';
 | 
						|
      wb_stb         <= '0';
 | 
						|
      wb_adr         <= (others => '0');
 | 
						|
      wb_dat_in      <= (others => '0');
 | 
						|
      -- UART TX
 | 
						|
      data_tx        <= (others => '0');
 | 
						|
      byte_ready_tx  <= '0';
 | 
						|
    elsif rising_edge(clk) then
 | 
						|
      case state is
 | 
						|
        when IDLE =>
 | 
						|
          if byte_ready_rx = '1' and data_rx = x"D5" then  -- Serial byte received. Is it the preambel?
 | 
						|
            state       <= CMD;
 | 
						|
            bytecounter <= 0;
 | 
						|
          end if;
 | 
						|
        when CMD =>
 | 
						|
          if byte_ready_rx = '1' then
 | 
						|
          -- TODO: Byte received. Do something
 | 
						|
          end if;
 | 
						|
        when EXEC =>
 | 
						|
          null;                         -- TODO: handle Wishbone communication
 | 
						|
        when REPLY =>
 | 
						|
          -- TODO: if reply_is_error = '1' then: wait for response that
 | 
						|
          -- indicates that the error is handled. Then switch back to command
 | 
						|
          -- mode. Else; Just wait for response to be sent.
 | 
						|
          null;
 | 
						|
        when HANG =>
 | 
						|
          state <= HANG;                -- End of FSM. Only way out is a reset
 | 
						|
      end case;
 | 
						|
    end if;
 | 
						|
  end process controlFSM;
 | 
						|
 | 
						|
 | 
						|
  ------ Asynchronous output assignments ---------------
 | 
						|
 | 
						|
end architecture RTL;
 |