0

我正在尝试在我的电脑和 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字节。谁能告诉我问题出在哪里?

4

0 回答 0