URL
https://opencores.org/ocsvn/uart_block/uart_block/trunk
Subversion Repositories uart_block
[/] [uart_block/] [trunk/] [hdl/] [iseProject/] [uart_control.vhd] - Rev 20
Go to most recent revision | Compare with Previous | Blame | View Log
--! uart control unit library IEEE; use IEEE.STD_LOGIC_1164.ALL; --! Use CPU Definitions package use work.pkgDefinitions.all; entity uart_control is Port ( rst : in std_logic; -- Global reset clk : in std_logic; -- Global clock WE : in std_logic; -- Write enable reg_addr : in std_logic_vector (1 downto 0); -- Register address start : in std_logic; -- Start (Strobe) done : out std_logic; -- Done (ACK) DAT_I : in std_logic_vector ((nBitsLarge-1) downto 0); -- Data Input (Wishbone) DAT_O : out std_logic_vector ((nBitsLarge-1) downto 0); -- Data output (Wishbone) baud_wait : out std_logic_vector ((nBitsLarge-1) downto 0); -- Signal to control the baud rate frequency data_byte_tx : out std_logic_vector((nBits-1) downto 0); -- 1 Byte to be send to serial_transmitter data_byte_rx : in std_logic_vector((nBits-1) downto 0); -- 1 Byte to be received by serial_receiver tx_data_sent : in std_logic; -- Signal comming from serial_transmitter tx_start : out std_logic; -- Signal to start sending serial data... rst_comm_blocks : out std_logic; -- Reset Communication blocks rx_data_ready : in std_logic); -- Signal comming from serial_receiver end uart_control; architecture Behavioral of uart_control is signal config_clk : std_logic_vector((nBitsLarge-1) downto 0); signal config_baud : std_logic_vector((nBitsLarge-1) downto 0); --signal byte_to_receive : std_logic_vector((nBits-1) downto 0); signal byte_to_transmitt : std_logic_vector((nBits-1) downto 0); signal controlStates : uartControl; signal sigDivRst : std_logic; signal sigDivDone : std_logic; signal sigDivQuotient : std_logic_vector((nBitsLarge-1) downto 0); --signal sigDivReminder : std_logic_vector((nBitsLarge-1) downto 0); signal sigDivNumerator : std_logic_vector((nBitsLarge-1) downto 0); signal sigDivDividend : std_logic_vector((nBitsLarge-1) downto 0); -- Divisor component component divisor is Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; quotient : out STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0); reminder : out STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0); numerator : in STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0); divident : in STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0); done : out STD_LOGIC); end component; begin -- Instantiate block for calculate division uDiv : divisor port map ( rst => sigDivRst, clk => clk, quotient => sigDivQuotient, reminder => open, -- Indicates that this port will not be connected to anything numerator => sigDivNumerator, divident => sigDivDividend, done => sigDivDone ); -- Process that read uart control registers process (rst, reg_addr, WE, start, byte_to_transmitt, data_byte_rx, rx_data_ready, config_clk, config_baud) begin if rst = '1' then DAT_O <= (others => 'Z'); else if (WE = '0') and (start = '1') then case reg_addr is when "00" => DAT_O <= config_clk; when "01" => DAT_O <= config_baud; when "10" => -- Byte that will be transmitted DAT_O <= "000000000000000000000000" & byte_to_transmitt; when "11" => -- Byte that will be received if rx_data_ready = '1' then DAT_O <= "000000000000000000000000" & data_byte_rx; --DAT_O <= "000000000000000000000000" & byte_to_receive; else DAT_O <= (others => 'Z'); end if; when others => DAT_O <= (others => 'Z'); end case; else DAT_O <= (others => 'Z'); end if; end if; end process; -- Process that populate the uart control registers process (rst, clk, reg_addr,WE,start) begin if rst = '1' then config_clk <= (others => '0'); config_baud <= (others => '0'); byte_to_transmitt <= (others => '0'); elsif rising_edge(clk) then if (WE = '1') and (start = '1') then case reg_addr is when "00" => config_clk <= DAT_I; when "01" => config_baud <= DAT_I; when "10" => -- Byte that will be transmitted byte_to_transmitt <= DAT_I((nBits-1) downto 0); when others => null; end case; end if; end if; end process; -- Process to handle the next state logic process (rst, clk, reg_addr, WE, start) variable baud_configured : std_logic; variable clk_configured : std_logic; variable div_result_baud_wait : std_logic_vector ((nBitsLarge-1) downto 0); begin if rst = '1' then controlStates <= idle; baud_configured := '0'; clk_configured := '0'; div_result_baud_wait := (others => '0'); done <= '0'; sigDivRst <= '1'; rst_comm_blocks <= '1'; tx_start <= '0'; --byte_to_receive <= (others => 'Z'); elsif rising_edge(clk) then case controlStates is when idle => done <= '0'; -- Go to config state if (reg_addr = "00") and (WE = '1') then controlStates <= config_state_clk; clk_configured := '1'; elsif (reg_addr = "01") and (WE = '1') then controlStates <= config_state_baud; baud_configured := '1'; end if; when config_state_clk => sigDivRst <= '1'; sigDivNumerator <= config_clk; if baud_configured = '0' then -- Baud not configured yet so wait for it... controlStates <= idle; done <= '1'; else -- If already configured wait for division completion... controlStates <= start_division; end if; when config_state_baud => sigDivRst <= '1'; sigDivDividend <= config_baud; if clk_configured = '0' then -- Clock not configured yet so wait for it... controlStates <= idle; done <= '1'; else -- If already configured wait for division completion... controlStates <= start_division; end if; when start_division => sigDivRst <= '0'; controlStates <= wait_division; when wait_division => if sigDivDone = '0' then controlStates <= wait_division; else -- Division done, get the result to put on the wait_cycles signal of the baud generator div_result_baud_wait := sigDivQuotient; controlStates <= config_state_baud_generator; end if; when config_state_baud_generator => -- Configure the wait_cycle for the desired baud rate... baud_wait <= div_result_baud_wait; controlStates <= rx_tx_state; done <= '1'; -- Control the serial_receiver or serial_transmitter block when rx_tx_state => rst_comm_blocks <= '0'; tx_start <= '0'; controlStates <= rx_tx_state; if (WE = '1') and (start = '1') then if reg_addr = "10" then controlStates <= tx_state_wait; done <= '0'; end if; end if; if (WE = '0') and (start = '1') then case reg_addr is when "11" => controlStates <= rx_state_wait; when "10" => done <= '1'; controlStates <= rx_tx_state; when others => null; end case; end if; if (start = '0') then done <= '0'; end if; -- Send data and wait to transmit when tx_state_wait => tx_start <= '1'; data_byte_tx <= byte_to_transmitt; if tx_data_sent = '0' then controlStates <= tx_state_wait; else controlStates <= rx_tx_state; done <= '1'; end if; -- Receive data and wait to receive when rx_state_wait => if rx_data_ready = '1' then -- Put an ack on the next cycle controlStates <= rx_state_ack; else controlStates <= rx_state_wait; done <= '0'; end if; -- Ack that we got a value when rx_state_ack => done <= '1'; controlStates <= rx_tx_state; end case; end if; end process; end Behavioral;
Go to most recent revision | Compare with Previous | Blame | View Log