我正在尝试在我的电脑和 nexys4 DDR 开发板之间建立 UART 通信。实际上,我使用这个板来运行 PicoBlaze(KCPSM6)的源代码,并且应该在 Picoblaze(板上)和 PicoTerm(来自我的电脑)之间建立通信。这是主要的:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library unisim;
use unisim.VCOMPONENTS.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Main is
Port ( uart_rx : in std_logic;
uart_tx : out std_logic;
clk_in: in std_logic);
end Main;
architecture Behavioral of Main is
component kcpsm6
generic( hwbuild : std_logic_vector(7 downto 0) := X"00";
interrupt_vector : std_logic_vector(11 downto 0) := X"3FF";
scratch_pad_memory_size : integer := 64);
port ( address : out std_logic_vector(11 downto 0);
instruction : in std_logic_vector(17 downto 0);
bram_enable : out std_logic;
in_port : in std_logic_vector(7 downto 0);
out_port : out std_logic_vector(7 downto 0);
port_id : out std_logic_vector(7 downto 0);
write_strobe : out std_logic;
k_write_strobe : out std_logic;
read_strobe : out std_logic;
interrupt : in std_logic;
interrupt_ack : out std_logic;
sleep : in std_logic;
reset : in std_logic;
clk : in std_logic);
end component;
component my_uart_control
generic( C_FAMILY : string := "7S";
C_RAM_SIZE_KWORDS : integer := 1;
C_JTAG_LOADER_ENABLE : integer := 0);
Port ( address : in std_logic_vector(11 downto 0);
instruction : out std_logic_vector(17 downto 0);
enable : in std_logic;
rdl : out std_logic;
clk : in std_logic);
end component;
component uart_tx6
Port ( data_in : in std_logic_vector(7 downto 0);
en_16_x_baud : in std_logic;
serial_out : out std_logic;
buffer_write : in std_logic;
buffer_data_present : out std_logic;
buffer_half_full : out std_logic;
buffer_full : out std_logic;
buffer_reset : in std_logic;
clk : in std_logic);
end component;
--
-- UART Receiver with integral 16 byte FIFO buffer
--
component uart_rx6
Port ( serial_in : in std_logic;
en_16_x_baud : in std_logic;
data_out : out std_logic_vector(7 downto 0);
buffer_read : in std_logic;
buffer_data_present : out std_logic;
buffer_half_full : out std_logic;
buffer_full : out std_logic;
buffer_reset : in std_logic;
clk : in std_logic);
end component;
component divizor_ceas is
Port (clk100: in std_logic;
clk50: out std_logic );
end component;
signal address : std_logic_vector(11 downto 0);
signal instruction : std_logic_vector(17 downto 0);
signal bram_enable : std_logic;
signal in_port : std_logic_vector(7 downto 0);
signal out_port : std_logic_vector(7 downto 0);
signal port_id : std_logic_vector(7 downto 0);
signal write_strobe : std_logic;
signal k_write_strobe : std_logic;
signal read_strobe : std_logic;
signal interrupt : std_logic;
signal interrupt_ack : std_logic;
signal kcpsm6_sleep : std_logic;
signal kcpsm6_reset : std_logic;
signal cpu_reset : std_logic;
signal rdl : std_logic;
--
-- When interrupt is to be used then the recommended circuit included below requires
-- the following signal to represent the request made from your system.
--
signal int_request : std_logic;
-- Signals used to create 50MHz clock from 450MHz differential clock
--
signal clk : std_logic;
--
-- Signals used to connect UART_TX6
--
signal uart_tx_data_in : std_logic_vector(7 downto 0);
signal write_to_uart_tx : std_logic;
signal uart_tx_data_present : std_logic;
signal uart_tx_half_full : std_logic;
signal uart_tx_full : std_logic;
signal uart_tx_reset : std_logic;
--
-- Signals used to connect UART_RX6
--
signal uart_rx_data_out : std_logic_vector(7 downto 0);
signal read_from_uart_rx : std_logic;
signal uart_rx_data_present : std_logic;
signal uart_rx_half_full : std_logic;
signal uart_rx_full : std_logic;
signal uart_rx_reset : std_logic;
--
-- Signals used to define baud rate
--
signal baud_count : integer range 0 to 26 := 0;
signal en_16_x_baud : std_logic := '0';
begin
--here i have a clock divider, to obtain a 50MHz clockrate
clock_divide:divizor_ceas port map(clk100=>clk_in, clk50=>clk);
processor: kcpsm6
generic map ( hwbuild => X"00",
interrupt_vector => X"3FF",
scratch_pad_memory_size => 64)
port map( address => address,
instruction => instruction,
bram_enable => bram_enable,
port_id => port_id,
write_strobe => write_strobe,
k_write_strobe => k_write_strobe,
out_port => out_port,
read_strobe => read_strobe,
in_port => in_port,
interrupt => interrupt,
interrupt_ack => interrupt_ack,
sleep => kcpsm6_sleep,
reset => kcpsm6_reset,
clk => clk);
kcpsm6_reset <= rdl;
kcpsm6_sleep <= '0';
interrupt <= interrupt_ack;
program_rom: my_uart_control --Name to match your PSM file
generic map(C_FAMILY => "7S", --Family 'S6', 'V6' or '7S'
C_RAM_SIZE_KWORDS => 1, --Program size '1', '2' or '4'
C_JTAG_LOADER_ENABLE => 1) --Include JTAG Loader when set to '1'
port map( address => address,
instruction => instruction,
enable => bram_enable,
rdl => rdl,
clk => clk);
tx: uart_tx6
port map ( data_in => uart_tx_data_in,
en_16_x_baud => en_16_x_baud,
serial_out => uart_tx,
buffer_write => write_to_uart_tx,
buffer_data_present => uart_tx_data_present,
buffer_half_full => uart_tx_half_full,
buffer_full => uart_tx_full,
buffer_reset => uart_tx_reset,
clk => clk);
rx: uart_rx6
port map ( serial_in => uart_rx,
en_16_x_baud => en_16_x_baud,
data_out => uart_rx_data_out,
buffer_read => read_from_uart_rx,
buffer_data_present => uart_rx_data_present,
buffer_half_full => uart_rx_half_full,
buffer_full => uart_rx_full,
buffer_reset => uart_rx_reset,
clk => clk);
baud_rate: process(clk)
begin
if clk'event and clk = '1' then
if baud_count = 26 then -- counts 27 states including zero
baud_count <= 0;
en_16_x_baud <= '1'; -- single cycle enable pulse
else
baud_count <= baud_count + 1;
en_16_x_baud <= '0';
end if;
end if;
end process baud_rate;
input_ports: process(clk)
begin
if clk'event and clk = '1' then
case port_id(0) is
-- Read UART status at port address 00 hex
when '0' => in_port(0) <= uart_tx_data_present;
in_port(1) <= uart_tx_half_full;
in_port(2) <= uart_tx_full;
in_port(3) <= uart_rx_data_present;
in_port(4) <= uart_rx_half_full;
in_port(5) <= uart_rx_full;
-- Read UART_RX6 data at port address 01 hex
-- (see 'buffer_read' pulse generation below)
when '1' => in_port <= uart_rx_data_out;
when others => in_port <= "XXXXXXXX";
end case;
-- Generate 'buffer_read' pulse following read from port address 01
if (read_strobe = '1') and (port_id(0) = '1') then
read_from_uart_rx <= '1';
else
read_from_uart_rx <= '0';
end if;
end if;
end process input_ports;
uart_tx_data_in <= out_port;
write_to_uart_tx <= '1' when (write_strobe = '1') and (port_id(0) = '1')
else '0';
constant_output_ports: process(clk)
begin
if clk'event and clk = '1' then
if k_write_strobe = '1' then
if port_id(0) = '1' then
uart_tx_reset <= out_port(0);
uart_rx_reset <= out_port(1);
end if;
end if;
end if;
end process constant_output_ports;
end Behavioral;
在这里我有汇编代码。我从中获取 my_uart_control 组件:
INCLUDE "uart_interface_routines.psm"
CONSTANT hex_value0, 00 ;lower byte
CONSTANT hex_value1, 01 ;upper byte
CONSTANT decimal0, 02 ;5 digit decimal value
CONSTANT decimal1, 03
CONSTANT decimal2, 04
CONSTANT decimal3, 05
CONSTANT decimal4, 06
CALL delay_1s
CALL reset_UART_macros
CALL clear_screen
; main program
main:
CALL send_CR
CALL send_CR
LOAD s5,">"
CALL UART_TX
CALL send_space
JUMP main
clear_screen: LOAD s5, ESC ;clear terminal sequence
CALL UART_TX
LOAD s5, "["
CALL UART_TX
LOAD s5, "2"
CALL UART_TX
LOAD s5, "J"
CALL UART_TX
CALL delay_1ms ;Delay for reliable operation
RETURN
;
cursor_home: LOAD s5, ESC ;Send cursor to upper-left of display
CALL UART_TX
LOAD s5, "["
CALL UART_TX
LOAD s5, "H"
CALL UART_TX
CALL delay_1ms ;Delay for reliable operation
RETURN
delay_1ms: LOAD s2, 00
LOAD s1, 18
LOAD s0, 6A
JUMP software_delay
;
;20ms is 1,000,000 clock cycles requiring 125,000 delay iterations
;
delay_20ms: LOAD s2, 01
LOAD s1, E8
LOAD s0, 48
JUMP software_delay
;
;1s is 50,000,000 clock cycles requiring 6,250,000 delay iterations
;
delay_1s: LOAD s2, 5F
LOAD s1, 5E
LOAD s0, 10
JUMP software_delay
;
; The delay loop decrements [s2,s1,s0] until it reaches zero
; Each decrement cycle is 4 instructions which is 8 clock cycles (160ns at 50MHz)
;
software_delay: SUB s0, 1'd
SUBCY s1, 0'd
SUBCY s2, 0'd
JUMP NZ, software_delay
RETURN
;
send_CR: LOAD s5, CR
JUMP UART_TX ;includes RETURN
send_space: LOAD s5, " "
JUMP UART_TX ;includes RETURN
;
uart_interface_routines.psm:
CONSTANT UART_status_port, 00 ; Read status
CONSTANT UART_Tx_data_present, 00000001'b ; Tx data_present - bit0
CONSTANT UART_Tx_half_full, 00000010'b ; half_full - bit1
CONSTANT UART_Tx_full, 00000100'b ; full - bit2
CONSTANT UART_Rx_data_present, 00001000'b ; Rx data_present - bit3
CONSTANT UART_Rx_half_full, 00010000'b ; half_full - bit4
CONSTANT UART_Rx_full, 00100000'b ; full - bit5
;
; Write data to UART_TX6
; ----------------------
;
CONSTANT UART_TX6_output_port, 01
;
; Read data from UART_RX6
; -----------------------
;
CONSTANT UART_RX6_input_port, 01
;
; Reset UART buffers (Constant Optimised Port)
; --------------------------------------------
;
CONSTANT reset_UART_port, 01
CONSTANT UART_tx_reset, 00000001'b ; uart_tx6 reset - bit0
CONSTANT UART_rx_reset, 00000010'b ; uart_rx6 reset - bit1
CONSTANT UART_reset, 00000011'b ; reset Tx and Rx
CONSTANT UART_operate, 00000000'b ; Tx and Rx free to operate
;
;
;--------------------------------------------------------------------------------------
; Routine to reset UART Buffers inside 'uart_tx6' and 'uart_rx6'
;--------------------------------------------------------------------------------------
;
; This routine will generate and apply an active High reset pulse to the FIFO
; buffers in both the transmitter and receiver macros.
;
; Note that the reset signals have been assigned to a constant optimised output port
; so the 'OUTPUTK' instructions are used and no registers contents are affected.
;
;
reset_UART_macros: OUTPUTK UART_reset, reset_UART_port
OUTPUTK UART_operate, reset_UART_port
RETURN
;
;
;--------------------------------------------------------------------------------------
; Routine to send one character to the UART Transmitter 'uart_tx6'
;--------------------------------------------------------------------------------------
;
; This routine will transmit the character provided in register 's5'.
;
; Before the character is output to the 'UART_TX6' macro the status of the FIFO buffer
; is checked to see if there is space. If the buffer is full then this routine will
; wait for space to become available (e.g. the time required for a previous character
; to be transmitted by the UART).
;
; Registers used s0 and s5 for the data (which is preserved)
;
UART_TX: INPUT s0, UART_status_port ;Check if buffer is full
TEST s0, UART_Tx_full
JUMP NZ, UART_TX ;wait if full
OUTPUT s5, UART_TX6_output_port
RETURN
;
;
;--------------------------------------------------------------------------------------
; Routine to attempt to receive one character from the UART Receiver 'uart_rx6'
;--------------------------------------------------------------------------------------
;
; This routine will attempt to receive one character from the 'UART_RX6' macro, and if
; successful, will return that character in register 's5' and the Zero flag will be
; reset (Z=0).
;
; If there are no characters available to be read from the FIFO buffer within the
; 'UART_RX6' macro then this routine will timeout after ~2,000 clock cycles (which is
; 40us at 50MHz) with the Zero flag set (Z=1). This timeout scheme ensures that KCPSM6
; cannot become stuck in this routine if no characters are received. If you do want
; KCPSM6 to wait indefinitely for a character to be received then either modify this
; routine or perform a test of the Zero flag and repeat the call to this routine as
; shown in this example...
;
; wait_for_UART_RX: CALL UART_RX
; JUMP Z, wait_for_UART_RX
;
;
; Registers used s0, s1 and s5.
;
UART_RX: LOAD s1, 167'd ;Timeout = 167 x (6 instructions x 2 clock cycles)
rx_timeout: INPUT s0, UART_status_port
TEST s0, UART_Rx_data_present ;Z=0 and C=1 when data present
JUMP NZ, read_Rx
SUB s1, 1'd
RETURN Z ;Timeout returns with Z=1 and C=0
JUMP rx_timeout
;
read_Rx: INPUT s5, UART_RX6_input_port ;read character from buffer
RETURN
;
;
波特率的值为 115200。我希望在无限循环中接收 '>' 和一些换行符,但我只接收到一些不可打印的字节。使用 putty 中的日志文件,我意识到我只收到ff
字节。谁能告诉我问题出在哪里?