Получение данных от микропроцессора VHDL Spartan 3A - PullRequest
0 голосов
/ 03 декабря 2011

У меня есть приложение, которое создает экземпляр микропроцессора, который мы разрабатываем на курсе vhdl, оно также отображает данные на ЖК-дисплее ПЛИС.

Мы протестировали микро и ЖК-дисплей отдельно, и они работают.

Теперь идея состоит в том, чтобы отобразить данные микро (это программа, которая генерирует ряды Фибоначчи) на ЖК-дисплее, но я не могу заставить его отображать условия серии.

Вот весь код, но я думаю, что часть, в которой проблема может быть, заключается в создании экземпляра микро, а затем, когда я получаю данные (процесс, чей список чувствительности имеет DATO_VALIDO и сбрасывается)

Возможно, он правильно обрабатывает термины, но когда я отображаю их на ЖК-дисплее, они отображаются не в правильном порядке.

Псевдокод:

if DATO_VALID is '1' then
    get value of ACC
    convert Bin2BCD
    convert BCD2ASCII
    print on LCD
end

Что я хочу сделать, это сохранить каждый член в разных сигналах после их преобразования в ASCII, это следующие сигналы: dT1, uT1, dT2, uT2 и т. Д. И т. Д.

И, наконец, на главном автомате у меня есть состояние для каждого из сигналов, содержащих значение, и оно должно показывать термины.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.bin_to_bcd_package.all;    -- Paquete con la definicion de la funcion "to_bcd" y puertos de mp4

entity lcd1_3A is
    port(
    clk, reset : in std_logic;
    LCD_DB : out std_logic_vector(7 downto 0);
    LCD_E, LCD_RS, LCD_RW : out std_logic;
    LED : out std_logic_vector(7 downto 0) );
end lcd1_3A;

architecture behavior of lcd1_3A is

    ------------------------------------------------------------------------
    -- Señales para la secuencia de Transmision ( estados)
    ------------------------------------------------------------------------
    type tx_sequence is (high_setup, high_hold, oneus, low_setup, low_hold, fortyus, done);
    signal tx_state : tx_sequence := done;
    signal tx_byte : std_logic_vector(7 downto 0);
    signal tx_init : std_logic := '0';
    signal SF_D : std_logic_vector(3 downto 0); -- 4 Data std_logic
    signal SF_CE0 : std_logic;

    ------------------------------------------------------------------------
    -- Señales para la secuencia de Inicalizacion ( estados)
    ------------------------------------------------------------------------
    type init_sequence is (idle, fifteenms, one, two, three, four, five, six, seven, eight, done);
    signal init_state : init_sequence := idle; -- El estado inicial es idle
    signal init_init, init_done : std_logic := '0'; -- 

    signal i : integer range 0 to 750000 := 0; -- Numero de ciclos para generar una duracion de 15ms
    signal i2 : integer range 0 to 2000 := 0;  -- Numero de ciclos para generar una duracion de 40us
    signal i3 : integer range 0 to 82000 := 0; -- Numero de ciclos para generar una duracion de 1.64ms
    signal cTerminos : integer range 0 to 8 := 0;

    signal SF_D0, SF_D1 : std_logic_vector(3 downto 0);
    signal LCD_E0, LCD_E1 : std_logic;
    signal mux : std_logic;

    ------------------------------------------------------------------------
    -- Señales para la Maquina de estados principal (8 estados), 4 caracteres
    ------------------------------------------------------------------------
    type display_state is (init, function_set, entry_set, set_display, clr_display, pause, set_addr,
                                    decenasT1, unidadesT1, decenasT2, unidadesT2, decenasT3, unidadesT3,
                                    decenasT4, unidadesT4, decenasT5, unidadesT5, decenasT6, unidadesT6,
                                    decenasT7, unidadesT7, decenasT8, unidadesT8, done);
    signal cur_state : display_state := init;

    ------------
    --
    ------------
    constant ram_addr_std_logics:integer:=5;-- Numero de std_logics para las direcciones del mp4
    constant ram_width:integer:=4;-- Tamaño de palabra de la memoria de programa mp4

    signal ACC: std_logic_vector (ram_width-1 downto 0);--salida del dato
    signal BANDERAS: std_logic_vector (2 downto 0);--registro de banderas ZVC
    signal DATO_VALIDO: std_logic;
    signal dT1,uT1,dT2,uT2,dT3,uT3,dT4,uT4,
             dT5,uT5,dT6,uT6,dT7,uT7,dT8,uT8 : std_logic_vector (7 downto 0) := "01000000";
    signal otro : std_logic_vector (7 downto 0);
begin

    ------------------------------------------------------------------------
    -- Instanciacion del microprocesador de 4 std_logics
    ------------------------------------------------------------------------    
    microprocesador: mp4 GENERIC MAP(ram_addr_std_logics, ram_width) PORT MAP(clk, reset, ACC, BANDERAS, DATO_VALIDO);

    process (DATO_VALIDO, reset)
        variable convBCD : std_logic_vector(11 downto 0) := (others => '0');
    begin
        if (reset = '1') then
            cTerminos <= 0;
        elsif (DATO_VALIDO = '1' and DATO_VALIDO'event) then
            cTerminos <= cTerminos + 1;
            if(cTerminos < 3) then
                case cTerminos is
                    when 1 =>
                        --convBCD := to_bcd("000"&BANDERAS(0)&ACC);
                        --dT1 <= x"3"&convBCD(7 downto 4);
                        --uT1 <= x"3"&convBCD(3 downto 0);
                        dT1 <= x"30";
                        uT1 <= x"3"&ACC;
                    when 2 =>
    --                  convBCD := to_bcd("000"&BANDERAS(0)&ACC);
    --                  dT2 <= x"3"&convBCD(7 downto 4);
    --                  uT2 <= x"3"&convBCD(3 downto 0);
                        dT2 <= x"30";
                        uT2 <= x"3"&ACC;
                    when 3 =>
    --                  convBCD := to_bcd("000"&BANDERAS(0)&ACC);
    --                  dT3 <= x"3"&convBCD(7 downto 4);
    --                  uT3 <= x"3"&convBCD(3 downto 0);
                        dT3 <= x"30";
                        uT3 <= x"3"&ACC;
                    when 4 =>
    --                  convBCD := to_bcd("000"&BANDERAS(0)&ACC);
    --                  dT4 <= x"3"&convBCD(7 downto 4);
    --                  uT4 <= x"3"&convBCD(3 downto 0);
                        dT4 <= x"30";
                        uT4 <= x"3"&ACC;
                    when 5 =>
    --                  convBCD := to_bcd("000"&BANDERAS(0)&ACC);
    --                  dT5 <= x"3"&convBCD(7 downto 4);
    --                  uT5 <= x"3"&convBCD(3 downto 0);
                        dT5 <= x"30";
                        uT5 <= x"3"&ACC;
                    when 6 =>
    --                  convBCD := to_bcd("000"&BANDERAS(0)&ACC);
    --                  dT6 <= x"3"&convBCD(7 downto 4);
    --                  uT6 <= x"3"&convBCD(3 downto 0);
                        dT6 <= x"30";
                        uT6 <= x"3"&ACC;
                    when 7 =>
                        convBCD := to_bcd("000"&BANDERAS(0)&ACC);
                        dT7 <= x"3"&convBCD(7 downto 4);
                        uT7 <= x"3"&convBCD(3 downto 0);
                    when 8 =>
                        convBCD := to_bcd("000"&BANDERAS(0)&ACC);
                        dT8 <= x"3"&convBCD(7 downto 4);
                        uT8 <= x"3"&convBCD(3 downto 0);
                    when others =>
                        otro <= x"FF";
                end case;
            end if;
        end if;
    end process;


    LCD_DB(7 downto 4) <= SF_D;
    LCD_DB(3 downto 0) <= "1111";

    LED <= tx_byte; -- El byte enviado al Data Display RAM del LCD se visualiza en los LEDs

    SF_CE0 <= '1'; -- Deshabilita la memoria intel strataflash, StrataFlash disabled. Full access to LCD
    LCD_RW <= '0'; -- Habilita la señal de escritura

    -- Establece cuando transmitir un comando/dato y cuando no
    with cur_state select
        tx_init <= '0' when init | pause | done, -- Estados en los que NO se transmite
            '1' when others; -- Transmite

    -- Selecciona el bus
    with cur_state select
        mux <= '1' when init, -- El mux vale 1, unicamente en el estado de init
            '0' when others;

    -- Establece el valor de la señal init_init
    with cur_state select
        init_init <= '1' when init,
            '0' when others;

    -- Establece el valor del puerto LCD_RS (register select)
    with cur_state select
        LCD_RS <= '0' when function_set|entry_set|set_display|clr_display|set_addr,
            '1' when others;

    -- Que dato se esta transmitiendo al LCD 
    with cur_state select
        tx_byte <= "00101000" when function_set,    -- 0x28, configure the display for operation on the Spartan-3E Starter Kit board.
            "00000110" when entry_set,              -- 0x06, set the display to automatically increment the address pointer
            "00001100" when set_display,            -- 0x0C, to turn the display on and disables the cursor and blinking
            "00000001" when clr_display,            -- 0x01, clear the display and return the cursor to the home position, the top-left corner
            "10000000" when set_addr,               -- 0x80, set the initial DD RAM address
            dT1 when decenasT1,
            uT1 when unidadesT1,
            dT2 when decenasT2,
            uT2 when unidadesT2,
            dT3 when decenasT3,
            uT3 when unidadesT3,
            dT4 when decenasT4,
            uT4 when unidadesT4,
            dT5 when decenasT5,
            uT5 when unidadesT5,
            dT6 when decenasT6,
            uT6 when unidadesT6,
            dT7 when decenasT7,
            uT7 when unidadesT7,
            dT8 when decenasT8,
            uT8 when unidadesT8,
            "00000000" when others;

    ------------------------------------------------------------------------
    -- Maquina de estados principal (8 estados),  4 caracteres
    ------------------------------------------------------------------------
    display: process(clk, reset)
    begin
        if(reset='1') then
            cur_state <= function_set;
        elsif(clk='1' and clk'event) then
            case cur_state is
                --Permanece en el estado de init, hasta que init_done = '1'
                when init =>
                    if(init_done = '1') then
                        cur_state <= function_set;
                    else
                        cur_state <= init;
                    end if;

                -- Todos los estados, excepto pause, utilizan el proceso transmit state machine
                -- Todos los estados, excepto pause, permanecen en el estado actual por una duracion de 40us
                when function_set =>
                    if(i2 = 2000) then
                        cur_state <= entry_set;
                    else
                        cur_state <= function_set;
                    end if; 

                when entry_set =>
                    if(i2 = 2000) then
                        cur_state <= set_display;
                    else
                        cur_state <= entry_set;
                    end if;

                when set_display =>
                    if(i2 = 2000) then
                        cur_state <= clr_display;
                    else
                        cur_state <= set_display;
                    end if;

                when clr_display =>
                    i3 <= 0;
                    if(i2 = 2000) then
                        cur_state <= pause;
                    else
                        cur_state <= clr_display;
                    end if;

                -- pause, permanece en el estado actual por una duracion de 1.64ms
                when pause =>
                    if(i3 = 82000) then
                        cur_state <= set_addr;
                        i3 <= 0;
                    else
                        cur_state <= pause;
                        i3 <= i3 + 1;
                    end if;

                when set_addr =>
                    if(i2 = 2000) then
                        cur_state <= decenasT1;
                    else
                        cur_state <= set_addr;
                    end if;

                when decenasT1 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT1;
                    else
                        cur_state <= decenasT1;
                    end if;

                when unidadesT1 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT2;
                    else
                        cur_state <= unidadesT1;
                    end if;

                when decenasT2 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT2;
                    else
                        cur_state <= decenasT2;
                    end if;

                when unidadesT2 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT3;
                    else
                        cur_state <= unidadesT2;
                    end if;

                when decenasT3 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT3;
                    else
                        cur_state <= decenasT3;
                    end if;

                when unidadesT3 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT4;
                    else
                        cur_state <= unidadesT3;
                    end if;

                when decenasT4 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT4;
                    else
                        cur_state <= decenasT4;
                    end if;

                when unidadesT4 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT5;
                    else
                        cur_state <= unidadesT4;
                    end if;

                when decenasT5 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT5;
                    else
                        cur_state <= decenasT5;
                    end if;

                when unidadesT5 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT6;
                    else
                        cur_state <= unidadesT5;
                    end if;

                when decenasT6 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT6;
                    else
                        cur_state <= decenasT6;
                    end if;

                when unidadesT6 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT7;
                    else
                        cur_state <= unidadesT6;
                    end if;

                when decenasT7 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT7;
                    else
                        cur_state <= decenasT7;
                    end if;

                when unidadesT7 =>
                    if(i2 = 2000) then
                        cur_state <= decenasT8;
                    else
                        cur_state <= unidadesT7;
                    end if;

                when decenasT8 =>
                    if(i2 = 2000) then
                        cur_state <= unidadesT8;
                    else
                        cur_state <= decenasT8;
                    end if;

                when unidadesT8 =>
                    if(i2 = 2000) then
                        cur_state <= done;
                    else
                        cur_state <= unidadesT8;
                    end if;

                when done =>
                    cur_state <= done;

            end case;
        end if;
    end process display;

    -- mux <= '1' when init '0' when others;
    with mux select
        SF_D <= SF_D0 when '0', --transmit
            SF_D1 when others;  --initialize
    with mux select
        LCD_E <= LCD_E0 when '0', --transmit
            LCD_E1 when others; --initialize

    --specified by datasheet
    transmit : process(clk, reset, tx_init)
    begin
        if(reset='1') then
            tx_state <= done;
        elsif(clk='1' and clk'event) then
            case tx_state is
                when high_setup => -- Permanece en este estado por 40ns
                    LCD_E0 <= '0';
                    SF_D0 <= tx_byte(7 downto 4);
                    if(i2 = 2) then
                        tx_state <= high_hold;
                        i2 <= 0;
                    else
                        tx_state <= high_setup;
                        i2 <= i2 + 1;
                    end if;

                when high_hold => -- Permanece en este estado por 240ns
                    LCD_E0 <= '1';
                    SF_D0 <= tx_byte(7 downto 4);
                    if(i2 = 12) then
                        tx_state <= oneus;
                        i2 <= 0;
                    else
                        tx_state <= high_hold;
                        i2 <= i2 + 1;
                    end if;

                when oneus => -- Permanece en este estado por 1us
                    LCD_E0 <= '0';
                    if(i2 = 50) then
                        tx_state <= low_setup;
                        i2 <= 0;
                    else
                        tx_state <= oneus;
                        i2 <= i2 + 1;
                    end if;

                when low_setup => -- Permanece en este estado por 40ns
                    LCD_E0 <= '0';
                    SF_D0 <= tx_byte(3 downto 0);
                    if(i2 = 2) then
                        tx_state <= low_hold;
                        i2 <= 0;
                    else
                        tx_state <= low_setup;
                        i2 <= i2 + 1;
                    end if;

                when low_hold => -- Permanece en este estado por 240ns
                    LCD_E0 <= '1';
                    SF_D0 <= tx_byte(3 downto 0);
                    if(i2 = 12) then
                        tx_state <= fortyus;
                        i2 <= 0;
                    else
                        tx_state <= low_hold;
                        i2 <= i2 + 1;
                    end if;

                when fortyus => -- Permanece en este estado por 40us
                    LCD_E0 <= '0';
                    if(i2 = 2000) then
                        tx_state <= done;
                        i2 <= 0;
                    else
                        tx_state <= fortyus;
                        i2 <= i2 + 1;
                    end if;

                when done => 
                    LCD_E0 <= '0';
                    if(tx_init = '1') then
                        tx_state <= high_setup;
                        i2 <= 0;
                    else
                        tx_state <= done;
                        i2 <= 0;
                    end if;

            end case;
        end if;
    end process transmit;


    ------------------------------------------------------------------------
    -- Maquina de estados para la secuencia de Inicalizacion (11 estados)
    ------------------------------------------------------------------------    
    --specified by datasheet
    power_on_initialize: process(clk, reset, init_init) --power on initialization sequence
    begin
        if(reset='1') then
            init_state <= idle;
            init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
        elsif(clk='1' and clk'event) then
            case init_state is
                when idle =>    
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(init_init = '1') then
                        init_state <= fifteenms;
                        i <= 0;
                    else
                        init_state <= idle;
                        i <= i + 1;
                    end if;

                when fifteenms => -- Permanece en este estado por 15ms 
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 750000) then
                        init_state <= one;
                        i <= 0;
                    else
                        init_state <= fifteenms;
                        i <= i + 1;
                    end if;

                when one =>  -- Permanece en este estado por 240ns
                    SF_D1 <= "0011";
                    LCD_E1 <= '1';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 11) then
                        init_state<=two;
                        i <= 0;
                    else
                        init_state<=one;
                        i <= i + 1;
                    end if;

                when two =>
                    LCD_E1 <= '0';  -- Permanece en este estado por 1.64ms
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 205000) then
                        init_state<=three;
                        i <= 0;
                    else
                        init_state<=two;
                        i <= i + 1;
                    end if;

                when three => -- Permanece en este estado por 240ns
                    SF_D1 <= "0011";
                    LCD_E1 <= '1';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 11) then 
                        init_state<=four;
                        i <= 0;
                    else
                        init_state<=three;
                        i <= i + 1;
                    end if;

                when four => -- Permanece en este estado por 100us
                    LCD_E1 <= '0';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 5000) then
                        init_state<=five;
                        i <= 0;
                    else
                        init_state<=four;
                        i <= i + 1;
                    end if;

                when five => -- Permanece en este estado por 240ns
                    SF_D1 <= "0011";
                    LCD_E1 <= '1';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 11) then
                        init_state<=six;
                        i <= 0;
                    else
                        init_state<=five;
                        i <= i + 1;
                    end if;

                when six => -- Permanece en este estado por 40us
                    LCD_E1 <= '0';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 2000) then
                        init_state<=seven;
                        i <= 0;
                    else
                        init_state<=six;
                        i <= i + 1;
                    end if;

                when seven =>  -- Permanece en este estado por 240ns
                    SF_D1 <= "0010";
                    LCD_E1 <= '1';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 11) then
                        init_state<=eight;
                        i <= 0;
                    else
                        init_state<=seven;
                        i <= i + 1;
                    end if;

                when eight =>  -- Permanece en este estado por 40us
                    LCD_E1 <= '0';
                    init_done <= '0'; -- Bandera de que NO ha terminado la inicializacion
                    if(i = 2000) then
                        init_state<=done;
                        i <= 0;
                    else
                        init_state<=eight;
                        i <= i + 1;
                    end if;

                when done =>
                    init_state <= done;
                    init_done <= '1'; -- Bandera que indica que TERMINO la inicializacion

            end case;

        end if;
    end process power_on_initialize;

end behavior;

1 Ответ

0 голосов
/ 24 марта 2012

Некоторые подробности об ошибке будут полезны. Вы пытались смоделировать свой код?

Но некоторые общие рекомендации относительно дизайна VHDL:

  • Разделите ваш дизайн на несколько компонентов / файлов: это упростит ведение обзора дизайна и упростит повторное использование определенного компонента в дальнейшем

  • Списки чувствительности процессов для синхронных процессов (процессов, в которых вы используете восходящий_элемент или 'событие) должны только содержать тактовый сигнал и, возможно, асинхронный сброс, если вам это нужно (один из ваших процессов имеет clk, reset и tx_init - tx_init там не принадлежит)

  • Не используйте комбинаторные сигналы в качестве часов: вы используете сигнал DATA_VALIDO в качестве часов в вашем первом процессе. Это комбинаторный сигнал, поэтому он будет немного отставать от ваших основных системных часов и может привести к всевозможным странным действиям. Только использует выделенные тактовые сигналы для тактовых триггеров (любой сигнал, который вы назначаете во время тактового процесса), так как они будут маршрутизироваться с использованием правильных линий синхронизации с низким перекосом. По сути, в вашем дизайне есть два часовых домена, что может быть одной из причин того, что ваш дизайн не работает. Вы можете использовать сигнал DATA_VALIDO в качестве разрешения часов или аналогичного, но не используйте его непосредственно в качестве часов.

  • Имитируйте ваш дизайн: большинство инструментов для проектирования FPGA должны иметь какой-то симулятор. Вы могли бы также научиться использовать его;)

...