Search code examples
vhdl

VHDL Component Port Mapping Issues


I am new to dealing with using COMPONENTS in VHDL and I understand how to port map simple things like slowing down a clock, however I have built a sequence dtetctor that seems to work well, but I want to have its' output trigger an input in my LCD write program and display to my LCD screen. How can I port map only the one signal over, or is there a better way of thinking about using the COMPONENT that I'm not thinking of?

How do i do direct entity instantiation? Could I use that here? I have been trying different ways to make my output Z be the input for the LCD on enable_0 but cant figure out how to not mess with all the other ports on that entity.

Thanks all

Matt

--Sequence detector(Mealy Machine-resetting)
LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY Sequence_Detector IS PORT(
    X : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
    CLK, LOAD: IN STD_LOGIC;
    LED : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
    Z: INOUT STD_LOGIC_VECTOR(1 DOWNTO 0));
END ENTITY;

ARCHITECTURE BEH OF Sequence_Detector IS
    TYPE state_type is (S0,S1,S2,S3,S4,S5,S6,S7,S8);
    SIGNAL TMP : STD_LOGIC_VECTOR(8 DOWNTO 0);
    SIGNAL clkout : STD_LOGIC;
    SIGNAL state : state_type;

    COMPONENT slowclk PORT(
        clk : IN STD_LOGIC;
        clkout : OUT STD_LOGIC);
    END COMPONENT;

BEGIN
    LED(17) <= LOAD;
    LED(8 DOWNTO 0) <= X;
    TMP <= X;

    state0: slowclk PORT MAP (clk, clkout);
    PROCESS (CLK)
    BEGIN
        IF (LOAD = '1') THEN
            IF (clkout'EVENT AND clkout = '1') THEN
                CASE state IS
                    WHEN S0 =>
                        IF X(8) = '0' THEN
                            state <= S0;      --1--
                            Z <= "00";
                        ELSE
                            state <= S1;
                            Z <= "00";
                        END IF;

                    WHEN S1 =>
                        IF X(7) = '0' THEN
                            state <= S0;      --1--
                            Z <= "00";
                        ELSE
                            state <= S2;
                            Z <= "00";
                        END IF;

                    WHEN S2 =>
                        IF X(6) = '0' THEN
                            state <= S3;      --0--
                            Z <= "00";
                        ELSE
                            state <= S2;
                            Z <= "00";
                        END IF;

                    WHEN S3 =>
                        IF X(5) = '0' THEN
                            state <= S0;      --1--
                            Z <= "00";
                        ELSE
                            state <= S4;
                            Z <= "00";
                        END IF;

                    WHEN S4 =>
                        IF X(4) = '0' THEN
                            state <= S5;      --0--
                            Z <= "00";
                        ELSE
                            state <= S2;
                            Z <= "00";
                        END IF;

                    WHEN S5 =>
                        IF X(3) = '0' THEN
                            state <= S6;      --0--
                            Z <= "00";
                        ELSE
                            state <= S0;
                            Z <= "00";
                        END IF;

                    WHEN S6 =>
                        IF X(2) = '0' THEN
                            state <= S0;      --1--
                            Z <= "00";
                        ELSE
                            state <= S7;
                            Z <= "00";
                        END IF;

                    WHEN S7 =>
                        IF X(1) = '0' THEN
                            state <= S0;      --1--
                            Z <= "00";
                        ELSE
                            state <= S8;
                            Z <= "00";
                        END IF;

                    WHEN S8 =>
                        IF X(0) = '0' THEN
                            state <= S0;      --0--
                            Z <= "11";
                        ELSE
                            state <= S2;
                            Z <= "01";
                        END IF;
                END CASE;
            END IF;
        END IF;
    END PROCESS;
END BEH;

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY slowclk IS PORT(
    clk : IN STD_LOGIC;
    clkout : OUT STD_LOGIC);
END slowclk;

ARCHITECTURE ckt OF slowclk IS
BEGIN
    PROCESS(clk)
        VARIABLE cnt : INTEGER RANGE 0 TO 50000000;
    BEGIN
        IF clk'EVENT AND clk='1' THEN
            IF cnt=50000000 THEN
                cnt:=0;
                clkout<='1';
            ELSE
                cnt:=cnt+1;
                clkout<='0';
            END IF;
        END IF;
    END PROCESS;
END ckt;

LIBRARY IEEE;
USE  IEEE.STD_LOGIC_1164.all;
USE  IEEE.STD_LOGIC_ARITH.all;
USE  IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY LCD IS
    -------------------------------------------------------------------
    --                        ASCII HEX TABLE
    --  Hex                 Low Hex Digit
    -- Value  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    ------\----------------------------------------------------------------
    --H  2 |  SP  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
    --i  3 |  0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
    --g  4 |  @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
    --h  5 |  P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
    --   6 |  `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
    --   7 |  p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ DEL
    -----------------------------------------------------------------------
PORT(
    reset, CLOCK_50        : IN  STD_LOGIC;
    enable_0               : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
    enable_1               : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
    LCD_RS, LCD_E          : OUT STD_LOGIC;
    LCD_RW                 : OUT   STD_LOGIC;
    LCD_ON                 : OUT STD_LOGIC;
    LCD_BLON               : OUT STD_LOGIC;
    DATA_BUS               : INOUT  STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY;

ARCHITECTURE Behavior OF LCD IS
    TYPE character_string IS ARRAY ( 0 TO 31 ) OF STD_LOGIC_VECTOR( 7 DOWNTO 0 );

    TYPE STATE_TYPE IS (HOLD, FUNC_SET, DISPLAY_ON, MODE_SET, Print_String,
                   LINE2, RETURN_HOME, DROP_LCD_E, RESET1, RESET2,
                   RESET3, DISPLAY_OFF, DISPLAY_CLEAR);

    SIGNAL   state, next_command           : STATE_TYPE;
    SIGNAL   LCD_display_string            : character_string;
    SIGNAL   DATA_BUS_VALUE, Next_Char     : STD_LOGIC_VECTOR(7 DOWNTO 0);
    SIGNAL   CLK_COUNT_400HZ               : STD_LOGIC_VECTOR(19 DOWNTO 0);
    SIGNAL   CHAR_COUNT                 : STD_LOGIC_VECTOR(4 DOWNTO 0);
    SIGNAL   CLK_400HZ_Enable,LCD_RW_INT   : STD_LOGIC;
    SIGNAL   Line1_chars, Line2_chars      : STD_LOGIC_VECTOR(127 DOWNTO 0);
BEGIN
    LCD_ON      <= '1';
    LCD_BLON    <= '1';

    PROCESS (clock_50)
    BEGIN
        CASE(enable_0) IS
            --passed--
            WHEN "11" => LCD_display_string <= (
                X"53",X"65",X"71",X"75",X"65",X"6E",X"63",X"65",X"20",X"50",X"61",X"73",X"73",X"65",X"64",X"20",
                X"4D",X"61",X"74",X"74",X"68",X"65",X"77",X"20",X"41",X"6E",X"64",X"65",X"72",X"73",X"6F",X"6E");
            WHEN "10" => LCD_display_string <= (
                X"20",X"20",X"20",X"20",X"45",X"45",X"43",X"45",X"20",X"33",X"34",X"33",X"20",X"20",X"20",X"20",
                X"4D",X"61",X"74",X"74",X"68",X"65",X"77",X"20",X"41",X"6E",X"64",X"65",X"72",X"73",X"6F",X"6E");
            --failed--
            WHEN "01" => LCD_display_string <= (
                X"53",X"65",X"71",X"75",X"65",X"6E",X"63",X"65",X"20",X"46",X"61",X"69",X"6C",X"65",X"64",X"20",
                X"4D",X"61",X"74",X"74",X"68",X"65",X"77",X"20",X"41",X"6E",X"64",X"65",X"72",X"73",X"6F",X"6E");
            WHEN "00" => LCD_display_string <= (
                X"20",X"20",X"20",X"20",X"45",X"45",X"43",X"45",X"20",X"33",X"34",X"33",X"20",X"20",X"20",X"20",
                X"4D",X"61",X"74",X"74",X"68",X"65",X"77",X"20",X"41",X"6E",X"64",X"65",X"72",X"73",X"6F",X"6E");
        END CASE;
    END PROCESS;

    -- BIDIRECTIONAL TRI STATE LCD DATA BUS
    DATA_BUS <= DATA_BUS_VALUE WHEN LCD_RW_INT = '0' ELSE "ZZZZZZZZ";

    -- get next character in display string
    Next_Char <= LCD_display_string(CONV_INTEGER(CHAR_COUNT));
    LCD_RW <= LCD_RW_INT;

    PROCESS
    BEGIN
        WAIT UNTIL CLOCK_50'EVENT AND CLOCK_50 = '1';
        IF RESET = '0' THEN
            CLK_COUNT_400HZ <= X"00000";
            CLK_400HZ_Enable <= '0';
        ELSE
            IF CLK_COUNT_400HZ < X"0F424" THEN
                CLK_COUNT_400HZ <= CLK_COUNT_400HZ + 1;
                CLK_400HZ_Enable <= '0';
            ELSE
                CLK_COUNT_400HZ <= X"00000";
                CLK_400HZ_Enable <= '1';
            END IF;
        END IF;
    END PROCESS;

    PROCESS (CLOCK_50, reset)
    BEGIN
        IF reset = '0' THEN
            state <= RESET1;
            DATA_BUS_VALUE <= X"38";
            next_command <= RESET2;
            LCD_E <= '1';
            LCD_RS <= '0';
            LCD_RW_INT <= '0';

        ELSIF CLOCK_50'EVENT AND CLOCK_50 = '1' THEN
            -- State Machine to send commands and data to LCD DISPLAY
            IF CLK_400HZ_Enable = '1' THEN
                CASE state IS
                    -- Set Function to 8-bit transfer and 2 line display with 5x8 Font size
                    -- see Hitachi HD44780 family data sheet for LCD command and timing details
                    WHEN RESET1 =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"38";
                        state <= DROP_LCD_E;
                        next_command <= RESET2;
                        CHAR_COUNT <= "00000";
                    WHEN RESET2 =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"38";
                        state <= DROP_LCD_E;
                        next_command <= RESET3;
                    WHEN RESET3 =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"38";
                        state <= DROP_LCD_E;
                        next_command <= FUNC_SET;
                    -- EXTRA STATES ABOVE ARE NEEDED FOR RELIABLE PUSHBUTTON RESET OF LCD
                    WHEN FUNC_SET =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"38";
                        state <= DROP_LCD_E;
                        next_command <= DISPLAY_OFF;
                    -- Turn off Display and Turn off cursor
                    WHEN DISPLAY_OFF =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"08";
                        state <= DROP_LCD_E;
                        next_command <= DISPLAY_CLEAR;
                    -- Clear Display and Turn off cursor
                    WHEN DISPLAY_CLEAR =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"01";
                        state <= DROP_LCD_E;
                        next_command <= DISPLAY_ON;
                    -- Turn on Display and Turn off cursor
                    WHEN DISPLAY_ON =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"0C";
                        state <= DROP_LCD_E;
                        next_command <= MODE_SET;
                    -- Set write mode to auto increment address and move cursor to the right
                    WHEN MODE_SET =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"06";
                        state <= DROP_LCD_E;
                        next_command <= Print_String;
                    -- Write ASCII hex character in first LCD character location
                    WHEN Print_String =>
                        state <= DROP_LCD_E;
                        LCD_E <= '1';
                        LCD_RS <= '1';
                        LCD_RW_INT <= '0';
                        -- ASCII character to output
                        IF Next_Char(7 DOWNTO  4) /= X"0" THEN
                            DATA_BUS_VALUE <= Next_Char;
                        ELSE
                            -- Convert 4-bit value to an ASCII hex digit
                            IF Next_Char(3 DOWNTO 0) >9 THEN
                                -- ASCII A...F
                                DATA_BUS_VALUE <= X"4" & (Next_Char(3 DOWNTO 0)-9);
                            ELSE
                                -- ASCII 0...9
                                DATA_BUS_VALUE <= X"3" & Next_Char(3 DOWNTO 0);
                            END IF;
                        END IF;
                        state <= DROP_LCD_E;
                        -- Loop to send out 32 characters to LCD Display  (16 by 2 lines)
                        IF (CHAR_COUNT < 31) AND (Next_Char /= X"FE") THEN
                            CHAR_COUNT <= CHAR_COUNT +1;
                        ELSE
                            CHAR_COUNT <= "00000";
                        END IF;
                        -- Jump to second line?
                        IF CHAR_COUNT = 15 THEN
                            next_command <= line2;
                        -- Return to first line?
                        ELSIF (CHAR_COUNT = 31) OR (Next_Char = X"FE") THEN
                            next_command <= return_home;
                        ELSE
                            next_command <= Print_String;
                        END IF;
                        -- Set write address to line 2 character 1
                    WHEN LINE2 =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"C0";
                        state <= DROP_LCD_E;
                        next_command <= Print_String;
                        -- Return write address to first character postion on line 1
                    WHEN RETURN_HOME =>
                        LCD_E <= '1';
                        LCD_RS <= '0';
                        LCD_RW_INT <= '0';
                        DATA_BUS_VALUE <= X"80";
                        state <= DROP_LCD_E;
                        next_command <= Print_String;
                        -- The next three states occur at the end of each command or data transfer to the LCD
                        -- Drop LCD E line - falling edge loads inst/data to LCD controller
                    WHEN DROP_LCD_E =>
                        LCD_E <= '0';
                        state <= HOLD;
                        -- Hold LCD inst/data valid after falling edge of E line
                    WHEN HOLD =>
                        state <= next_command;
                END CASE;
            END IF;
        END IF;
    END PROCESS;
END Behavior;

Solution

  •     LIBRARY ieee;
        USE ieee.std_logic_1164.all;
    
        ENTITY top_module IS PORT(
            X : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
            CLK, LOAD: IN STD_LOGIC;
            LCD_RS, LCD_E          : OUT STD_LOGIC;
            LCD_RW                 : OUT   STD_LOGIC;
            LCD_ON                 : OUT STD_LOGIC;
            LCD_BLON               : OUT STD_LOGIC;
            );
        END ENTITY;
    
        ARCHITECTURE Behavior OF top_module IS
    
        component Sequence_Detector IS PORT(
            X : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
            CLK, LOAD: IN STD_LOGIC;
            LED : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
            Z: INOUT STD_LOGIC_VECTOR(1 DOWNTO 0));
        END component;
    
       component slowclk IS PORT(
            clk : IN STD_LOGIC;
            clkout : OUT STD_LOGIC);
       END component;
    
       component LCD is PORT(
            reset, CLOCK_50        : IN  STD_LOGIC;
            enable_0               : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
            enable_1               : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
            LCD_RS, LCD_E          : OUT STD_LOGIC;
            LCD_RW                 : OUT   STD_LOGIC;
            LCD_ON                 : OUT STD_LOGIC;
            LCD_BLON               : OUT STD_LOGIC;
            DATA_BUS               : INOUT  STD_LOGIC_VECTOR(7 DOWNTO 0));
       END component;
    
    
       begin
    
       Instance_sequence_detector:
             port map ( X => X,
                       CLK => clkout,
                       LOAD => LOAD,
                       LED => LED,
                       Z => Z );
    
       Instance_slowclk:
         port map ( clk   => clk,
                   clkout => clkout
                );
    
       Instance_LCD:
         port map(reset => reset,
                 CLOCK_50 => clkout,
                 enable_0 => enable_0,
                 enable_1 => enable_1,
                 LCD_RS => LCD_RS,
                 LCD_E => LCD_E,
                 LCD_RW => LCD_RW,
                 LCD_ON => LCD_ON,
                 LCD_BLON => LCD_BLON,
                 DATA_BUS => DATA_BUS
                 );
    

    You can instantiate those modules in your top module like this. Just map the corresponding in and out ports from block to block.