我正在尝试将 UART 通信与 Lattice machox3 和 ft232R 一起使用。我正在尝试使用在 eewiki(此处)上找到的 VHDL 文件。出于某种原因,当我模拟它时,我无法让 tx 工作。我究竟做错了什么?我可以使用一个简单的 uart 实现吗?我试着自己做,我只是想传播,但我没有不成功。
这是Active hdl给我的波形
这是我用来让这个组件工作的顶级文件。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--library machXO3;
--use machXO3.all;
entity UART_TOP is generic (
divisor : integer := 2604 -- Set the Baud Rate Divisor here.
-- Some common values: 300 Baud = 83333, 9600 Baud = 2604, 115200 Baud = 217, 921600 Baud = 27
);
PORT(
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC;
CLOCK_UART : in STD_LOGIC;
DIN : IN STD_LOGIC_VECTOR(15 downto 0)
);
end UART_TOP;
architecture Behavior of UART_TOP is
SIGNAL INTERNAL_CLOCK : STD_LOGIC;
SIGNAL MUX_0 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_1 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_S : STD_LOGIC_VECTOR(1 downto 0);
SIGNAL txEN: STD_LOGIC_VECTOR(0 downto 0);
SIGNAL counter : STD_LOGIC;
SIGNAL DATAsnd : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL LOAD : STD_LOGIC;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT NOTM is
PORT(
Input : in STD_LOGIC;
Output : out STD_LOGIC
);
END COMPONENT;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT InputBuffer is
generic(n: natural);
PORT(
clk : in STD_LOGIC;
En : in STD_LOGIC; -- 0 is enabled
Input : in STD_LOGIC_VECTOR (n-1 downto 0);
Output : out STD_LOGIC_VECTOR (n-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- MUX04_2_1 --
---------------------------------------------------
COMPONENT MUX421 is
generic (
DATAWIDTH : natural := 8
);
port(
A : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
B : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
C : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
D : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
S : in STD_LOGIC_VECTOR(1 downto 0);
O : OUT STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- Binary Counter --
---------------------------------------------------
COMPONENT binary_counter is
generic(
MIN_COUNT : natural := 0;
MAX_COUNT : natural := 17
);
port(
clk : in std_logic;
reset : in std_logic;
enable : in std_logic; -- 0 is enabled
q : out STD_LOGIC_VECTOR(MAX_COUNT-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- UART. Mach0X3 --
---------------------------------------------------
COMPONENT uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END COMPONENT;
begin
-- UART
DATAOUT: UART_c
PORT MAP ( CLK => CLOCK_UART, --system clock
reset_n =>reset_n, --ascynchronous reset
tx_ena => tx_ena,--txEN(0), --initiate transmission
tx_data => DIN(7 downto 0), --data to transmit
rx =>'0' , --receive pin
tx => tx, --transmit pin
tx_busy => tx_busy
);
--UART LOAD
--LOADER: NOTM
--PORT MAP (INPUT => LOAD, OUTPUT => counter);
-- DATA to MUX
--MUX: MUX421
--PORT MAP (s => MUX_S, A => MUX_0, B => MUX_1, C => X"0D", D => X"0A", O => DO-- DATAsnd
--); -- C => X"0D", D => X"0A" cartidge return and line feed
-- Counter to mux
--cntr: binary_counter
--generic map (MAX_COUNT => 2)
--PORT MAP (
--clk => counter,
--reset => RESET,
--enable => ENABLE,
--q => MUX_S
--);
-- Counter to load
--Load_UART: binary_counter
--generic map (MAX_COUNT => 1)
--PORT MAP (
--clk => CLOCK_UART,
--reset => RESET,
--enable => LOAD,
--q => txEN
--);
--DATA to UART
--UARTBUFFER_0: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(15 downto 8), OUTPUT => MUX_0);
--DATA to UART
--UARTBUFFER_1: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(7 downto 0), OUTPUT => MUX_1);
end Behavior;
这是UART本身
--------------------------------------------------------------------------------
--
-- FileName: uart_c.vhd
-- Dependencies: none
-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 5/26/2017 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END uart_c;
ARCHITECTURE logic OF uart_c IS
TYPE tx_machine IS(idle, transmit); --tranmit state machine data type
TYPE rx_machine IS(idle, receive); --receive state machine data type
SIGNAL tx_state : tx_machine; --transmit state machine
SIGNAL rx_state : rx_machine; --receive state machine
SIGNAL baud_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the baud rate
SIGNAL os_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the oversampling rate
SIGNAL parity_error : STD_LOGIC; --receive parity error flag
SIGNAL rx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of receive parity
SIGNAL tx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of transmit parity
SIGNAL rx_buffer : STD_LOGIC_VECTOR(parity+d_width DOWNTO 0) := (OTHERS => '0'); --values received
SIGNAL tx_buffer : STD_LOGIC_VECTOR(parity+d_width+1 DOWNTO 0) := (OTHERS => '1'); --values to be transmitted
BEGIN
--generate clock enable pulses at the baud rate and the oversampling rate
PROCESS(reset_n, clk)
VARIABLE count_baud : INTEGER RANGE 0 TO clk_freq/baud_rate-1 := 0; --counter to determine baud rate period
VARIABLE count_os : INTEGER RANGE 0 TO clk_freq/baud_rate/os_rate-1 := 0; --counter to determine oversampling period
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
baud_pulse <= '0'; --reset baud rate pulse
os_pulse <= '0'; --reset oversampling rate pulse
count_baud := 0; --reset baud period counter
count_os := 0; --reset oversampling period counter
ELSIF(clk'EVENT AND clk = '1') THEN
--create baud enable pulse
IF(count_baud < clk_freq/baud_rate-1) THEN --baud period not reached
count_baud := count_baud + 1; --increment baud period counter
baud_pulse <= '0'; --deassert baud rate pulse
ELSE --baud period reached
count_baud := 0; --reset baud period counter
baud_pulse <= '1'; --assert baud rate pulse
count_os := 0; --reset oversampling period counter to avoid cumulative error
END IF;
--create oversampling enable pulse
IF(count_os < clk_freq/baud_rate/os_rate-1) THEN --oversampling period not reached
count_os := count_os + 1; --increment oversampling period counter
os_pulse <= '0'; --deassert oversampling rate pulse
ELSE --oversampling period reached
count_os := 0; --reset oversampling period counter
os_pulse <= '1'; --assert oversampling pulse
END IF;
END IF;
END PROCESS;
--receive state machine
PROCESS(reset_n, clk)
VARIABLE rx_count : INTEGER RANGE 0 TO parity+d_width+2 := 0; --count the bits received
VARIABLE os_count : INTEGER RANGE 0 TO os_rate-1 := 0; --count the oversampling rate pulses
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear receive bit counter
rx_busy <= '0'; --clear receive busy signal
rx_error <= '0'; --clear receive errors
rx_data <= (OTHERS => '0'); --clear received data output
rx_state <= idle; --put in idle state
ELSIF(clk'EVENT AND clk = '1' AND os_pulse = '1') THEN --enable clock at oversampling rate
CASE rx_state IS
WHEN idle => --idle state
rx_busy <= '0'; --clear receive busy flag
IF(rx = '0') THEN --start bit might be present
IF(os_count < os_rate/2) THEN --oversampling pulse counter is not at start bit center
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= idle; --remain in idle state
ELSE --oversampling pulse counter is at bit center
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear the bits received counter
rx_busy <= '1'; --assert busy flag
rx_state <= receive; --advance to receive state
END IF;
ELSE --start bit not present
os_count := 0; --clear oversampling pulse counter
rx_state <= idle; --remain in idle state
END IF;
WHEN receive => --receive state
IF(os_count < os_rate-1) THEN --not center of bit
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= receive; --remain in receive state
ELSIF(rx_count < parity+d_width) THEN --center of bit and not all bits received
os_count := 0; --reset oversampling pulse counter
rx_count := rx_count + 1; --increment number of bits received counter
rx_buffer <= rx & rx_buffer(parity+d_width DOWNTO 1); --shift new received bit into receive buffer
rx_state <= receive; --remain in receive state
ELSE --center of stop bit
rx_data <= rx_buffer(d_width DOWNTO 1); --output data received to user logic
rx_error <= rx_buffer(0) OR parity_error OR NOT rx; --output start, parity, and stop bit error flag
rx_busy <= '0'; --deassert received busy flag
rx_state <= idle; --return to idle state
END IF;
END CASE;
END IF;
END PROCESS;
--receive parity calculation logic
rx_parity(0) <= parity_eo;
rx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
rx_parity(i+1) <= rx_parity(i) XOR rx_buffer(i+1);
END GENERATE;
WITH parity SELECT --compare calculated parity bit with received parity bit to determine error
parity_error <= rx_parity(d_width) XOR rx_buffer(parity+d_width) WHEN 1, --using parity
'0' WHEN OTHERS; --not using parity
--transmit state machine
PROCESS(reset_n, clk)
VARIABLE tx_count : INTEGER RANGE 0 TO parity+d_width+3 := 0; --count bits transmitted
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
tx_count := 0; --clear transmit bit counter
tx <= '1'; --set tx pin to idle value of high
tx_busy <= '1'; --set transmit busy signal to indicate unavailable
tx_state <= idle; --set tx state machine to ready state
ELSIF(clk'EVENT AND clk = '1') THEN
CASE tx_state IS
WHEN idle => --idle state
IF(tx_ena = '1') THEN --new transaction latched in
tx_buffer(d_width+1 DOWNTO 0) <= tx_data & '0' & '1'; --latch in data for transmission and start/stop bits
IF(parity = 1) THEN --if parity is used
tx_buffer(parity+d_width+1) <= tx_parity(d_width); --latch in parity bit from parity logic
END IF;
tx_busy <= '1'; --assert transmit busy flag
tx_count := 0; --clear transmit bit count
tx_state <= transmit; --proceed to transmit state
ELSE --no new transaction initiated
tx_busy <= '0'; --clear transmit busy flag
tx_state <= idle; --remain in idle state
END IF;
WHEN transmit => --transmit state
IF(baud_pulse = '1') THEN --beginning of bit
tx_count := tx_count + 1; --increment transmit bit counter
tx_buffer <= '1' & tx_buffer(parity+d_width+1 DOWNTO 1); --shift transmit buffer to output next bit
END IF;
IF(tx_count < parity+d_width+3) THEN --not all bits transmitted
tx_state <= transmit; --remain in transmit state
ELSE --all bits transmitted
tx_state <= idle; --return to idle state
END IF;
END CASE;
tx <= tx_buffer(0); --output last bit in transmit transaction buffer
END IF;
END PROCESS;
--transmit parity calculation logic
tx_parity(0) <= parity_eo;
tx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
tx_parity(i+1) <= tx_parity(i) XOR tx_data(i);
END GENERATE;
END logic;
这是测试台
-- VHDL Test Bench Created from source file UART_TOP.vhd -- Sun Aug 19 12:41:55 2018
--
-- Notes:
-- 1) This testbench template has been automatically generated using types
-- std_logic and std_logic_vector for the ports of the unit under test.
-- Lattice recommends that these types always be used for the top-level
-- I/O of a design in order to guarantee that the testbench will bind
-- correctly to the timing (post-route) simulation model.
-- 2) To use this template as your testbench, change the filename to any
-- name of your choice with the extension .vhd, and use the "source->import"
-- menu in the ispLEVER Project Navigator to import the testbench.
-- Then edit the user defined section below, adding code to generate the
-- stimulus for your design.
-- 3) VHDL simulations will produce errors if there are Lattice FPGA library
-- elements in your design that require the instantiation of GSR, PUR, and
-- TSALL and they are not present in the testbench. For more information see
-- the How To section of online help.
--
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
COMPONENT UART_TOP
PORT(
reset_n : IN std_logic;
tx_ena : IN std_logic;
CLOCK_UART : IN std_logic;
DIN : IN std_logic_vector(15 downto 0);
tx_busy : OUT std_logic;
tx : OUT std_logic
);
END COMPONENT;
SIGNAL reset_n : std_logic;
SIGNAL tx_ena : std_logic;
SIGNAL tx_busy : std_logic;
SIGNAL tx : std_logic;
SIGNAL CLOCK_UART : std_logic;
SIGNAL DIN : std_logic_vector(15 downto 0);
constant half_period : time := 10 ns;
BEGIN
-- Please check and add your generic clause manually
uut: UART_TOP PORT MAP(
reset_n => reset_n,
tx_ena => tx_ena,
tx_busy => tx_busy,
tx => tx,
CLOCK_UART => CLOCK_UART,
DIN => DIN
);
-- *** Test Bench - User Defined Section ***
tb : PROCESS
BEGIN
reset_n <= '1';
tx_ena <= '0';
DIN <= B"0101010101010101";
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
tx_ena <= '1';
loop
CLOCK_UART <= '1';
wait for half_period ;
tx_ena <= '0';
CLOCK_UART <= '0';
wait for half_period ;
end loop;
END PROCESS;
-- *** End Test Bench - User Defined Section ***
END;