------------------------------------------------------------------------------- -- Title : MachXO2 Serial Configuration -- Project : tiny-xo2 ------------------------------------------------------------------------------- -- File : top.vhd -- Author : Mario Hüttel -- 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, 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 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;