0
votes

I'm writing some VHDL so I can interface a character LCD with my FPGA.

It goes as follows:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity Parallel_Interface_Main is

    port(
    Clock               : in            std_logic;
    Read_Write      : out           std_logic;
    Register_Select: out            std_logic;
    Enable          : out           std_logic;
    Busy                : buffer    std_logic;
    Data_In         : buffer        std_logic_vector(7 downto 0);
    Data_Line       : buffer        std_logic_vector(7 downto 0)
    );

end Parallel_Interface_Main;

architecture ParallelBehaviour of Parallel_Interface_Main is

signal initialized: std_logic := '0';

begin

Enable <= Clock;

initialize: process(Clock)
begin

if(Clock'event and Clock = '1') then

        Register_Select <= '0';
        Read_Write <= '1';
        Busy <= Data_Line(7);

        if(Busy = '0' and initialized = '0') then

            Register_Select <= '0';
            Read_Write <= '0';

            case Data_Line is

                    when "UUUUUUUU" => 
                            Data_Line <= "00111100";
                    when "00111100" => 
                            Data_Line <= "00001110";
                    when "00001110" => 
                            Data_Line <= "00000110";
                    when "00000110" => 
                            Data_Line <= "00000001";
                            initialized <= '1';
                    when others =>
                            Data_Line <= "ZZZZZZZZ";
            end case;

        end if;

        if(Busy = '0' and initialized = '1') then

            Register_Select <= '1';
            Read_Write <= '0';

            case Data_In is
                when "UUUUUUUU" =>
                    Data_In <= "01010010";
                when "01010001" =>
                    Data_In <= "01010000";
                when others =>
                    Data_In <= "ZZZZZZZZ";
            end case;

            Data_Line <= Data_In;

        end if;
end if;

end process;

end ParallelBehaviour;

Basically, the LCD sends back a busy flag when it is processing an instruction, so I wrote my code to only execute when the busy flag is 0. Since I don't have the LCD hooked up to my FPGA yet, to test this code I mapped the busy signal to a push button on the board with the least significant 4 bits of "Data Line" mapped to a couple of LEDs, just so I could see if the board was cycling through the eight bit codes.

Now when I upload the programming files to the FPGA and press the push button mapped to "Busy," there is no change in the state of the Data_Line bits. Is this a result of faulty VHDL? Or is it the fact that I mapped Busy to a pushbutton while the FPGA is clocked at 125 MHz. I am not experienced enough with FPGAs to know exactly what is going on.

I'm using an Altera Arria V GX FPGA.

1
Your code has several faults, but before one could address them all, I would like to ask for the exact board and LCD controller name. Here are some faults: (1) You can not test a signal for 'U'. (2) The LCD bus does not run at 125 MHz, normally it's somewhere in the kHz to low MHz regions. 3) You can not test for busy in the same cycle, while you are writing zero to the bus, because the busy bit is one of the data bits.Paebbels
First question : Did it work in simulation? Just looking at it I can answer that : no it did not. Make it work in simulation and you'll have a much easier time making it work in hardware. Secondly, Data_In is a Buffer port : it is either very poorly named, or it is supposed to be an In port...user_1818839
Hello Brian, thanks for the help and don't laugh at my code too much. (1) So should I just give my signal a default value and use that as the first when in the case statement? (2) I understand that the LCD controller runs on a much lower frequency which is why I'm polling the data bus for the busy signal. (3) When should I poll the busy signal? in between the falling and rising edges? It actually did work in the simulation, exactly how I intended. I will use Data_In eventually to send in data to this entity that can be forwarded to the LCD. The LCD controller is the common HD44780fat balls

1 Answers

1
votes

This should be a comment but my rep is not high enough.

First some cleanup.

Did you really mean buffer? And did you really want to make Data_In and Data_Line bi-directional ports? If you don't want bi-directional/tri-state port please use "in" and "out" instead and don't use Z.

Read_Write is just a delayed version of busy is that intentional?

I am confused about Data_in. I think Data_in should be an input and Data_Line should be an output. Or the they are meant to be bi-directional ports why do you have two?

A neat hint for you U will map to '0' in synthesis and I suggest you don't use it for synthesis-able modules

Either way I think your problem with not be able to view the changes on the chip might be that they are happening to fast. Have you denounced your buttion (look up debouncers). And then fed it through a rising/falling edge detection (compare the signal with a delayed version of itself). Without these steps the changes would be happening to fast for you to see. With the step you should be able to push the button for once each separate change.

Basically what I'm trying to say I need more information (this would be a comment if I had enough rep)