Стенд за изпитване на UART приемник

Нов съм в VHDL и се опитвам да проверя UART приемника как работи. Синтезирах кода по-долу (цитиран от книгата) и е добре, но ако има нужда от повече, уведомете ме :). Честотата за моята платка е 100 Mhz и данните, които искам да получа, са 8 бита, скоростта на предаване е 115 200, как трябва да са часовникът и отметката в тестовия стенд или кой е правилният тестов стенд тук?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity uart_rx is
    generic(
        data_bits: integer := 8;      --  #  d a t a   b i t s  
        stop_bit_ticks: integer := 16   --  #  t i c k s   f o r   s t o p   b i t s  
    );
    Port ( rx : in STD_LOGIC;
           clk : in STD_LOGIC;
           reset: in STD_LOGIC;
           tick : in STD_LOGIC;
           rx_done : out STD_LOGIC;
           data_out : out STD_LOGIC_VECTOR (7 downto 0));
end uart_rx;
architecture arch of uart_rx is
    type state_type is (idle, start, data, stop);
    SIGNAL state_reg, state_next: state_type;
    SIGNAL s_reg, s_next: UNSIGNED(3 downto 0);
    SIGNAL n_reg, n_next: UNSIGNED(2 downto 0);
    SIGNAL b_reg, b_next: STD_LOGIC_VECTOR(7 downto 0);
begin
--  FSMD  s t a t e   &  d a t a   r e g i s t e r s  
    process(clk, reset) -- FSMD state and data regs.
    begin
        if (reset = '1') then
            state_reg <= idle;
            s_reg <= (others => '0');
            n_reg <= (others => '0');
            b_reg <= (others => '0');
            --rx_done <= '0';
        --  rx <= '1';
        elsif (clk'event and clk='1') then
            state_reg <= state_next;
            s_reg <= s_next;
            n_reg <= n_next;
            b_reg <= b_next;
        end if;
    end process;
   --  n e x t - s t a t e   l o g i c   &  d a t a   p a t h   f u n c t i o n a l   u n i t s / r o u t i n g
    process (state_reg, s_reg, n_reg, b_reg, tick, rx)
    begin
        state_next <= state_reg;
        s_next <= s_reg;
        n_next <= n_reg;
        b_next <= b_reg;
        rx_done <= '0';
        case state_reg is
        when idle =>
            if (rx = '0') then
            state_next <= start;
            s_next <= (others => '0');
            end if;
        when start =>
            if (tick = '1') then
                if (s_reg = 7) then
                    state_next <= data;
                    s_next <= (others => '0');
                    n_next <= (others => '0');
                else
                    s_next <= s_reg + 1;
                end if;
            end if;
        when data =>
            if (tick = '1') then
                if (s_reg = 15) then
                    s_next <= (others => '0');
                    b_next <= rx & b_reg(7 downto 1);
                    if (n_reg = (data_bits - 1)) then
                        state_next <= stop;
                    else
                        n_next <= n_reg + 1;
                    end if;
                else
                    s_next <= s_reg + 1;
                end if;
            end if;
        when stop =>
            if (tick = '1') then
                if (s_reg = (stop_bit_ticks - 1)) then
                    state_next <= idle;
                    rx_done <= '1';
                else
                    s_next <= s_reg + 1;
                end if;
            end if;
        end case;
    end process;
    data_out <= b_reg; 
end arch;

person Alsphere    schedule 07.04.2015    source източник
comment
Това изглежда взето за глава 7 от книгата на Pong „Прототипиране на FPGA чрез VHDL примери“. Има генератор на скорост на предаване, споменат по-рано в главата, което означава, че трябва да използвате брояч, подобен на този в 4.3.2. Името на файла list_ch04_11_mod_m.vhd е в кода, който върви с книгата. Не си спомняйте каква тактова честота очаква, може да се наложи да прочетете книгата или да погледнете демонстрационната платка, която препоръчва.   -  person    schedule 07.04.2015


Отговори (1)


Обикновено UART приемниците работят с 8 пъти битрейт. Ако вашият битрейт е 115200, това означава честота на дискретизация 921600. Ако работите на 100 Mzh, ще трябва да създадете делител на часовника, за да получите от 100 MHz до желаната честота на дискретизация. За да преминете от 921600 на 100 MHz ще работи следното:

100 MHz = 100 000 000 Hz

921600 проби/сек = 921 600 Hz

делител = 100 000 000/921 600 = 108,51.

По този начин ще ви е необходим брояч, който ще брои до 109 (ние закръгляме, тъй като трябва да вземаме проби с цяло число от тактовата честота) на rising_edge(clock), след което да повишите сигнал за активиране, който казва на вашия компонент, че е време да вземе проби линия и нулирайте брояча. Примерът по-горе предполага 8 проби/бит, което е типично, доколкото знам. По този начин, ако зададете периода на вашия основен часовник в симулацията да бъде 1ns и настроите веригата на брояча, която описах по-горе, трябва да получите тестовия стенд, който търсите.

РЕДАКТИРАНЕ: предупреждение за неравномерно деление на часовника

Почти забравих да спомена това. Тъй като вашата тактова честота не се разделя равномерно на побитовата скорост за UART, трябва да се внимава допълнително, когато се кодира тази схема. Вашата честота на дискретизация ще се движи по-късно и по-късно в предаването със схемата, която предложих. Вероятно ще трябва да добавите просто отместване, за да промените брояча си на 108 на четните битове, за да сте по-изравнени с входящите битове данни.

Вижте тук за още информация: https://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed

person NKamrath    schedule 09.04.2015