BlackHelicopter
Full Member level 2
The code below compiles, however during simulation db = 'XX' and I get an error "Found Logic Contention."
I'm trying to read/write from inout db. The purpose of reading is to poll the busy flag on db(7) after writing an instruction. (HD44780). I believe I'm doing the inout port wrong?
Also I'm rather new to VHDL, so if any of you would approach it differently please let me know.
Thanks!
I'm trying to read/write from inout db. The purpose of reading is to poll the busy flag on db(7) after writing an instruction. (HD44780). I believe I'm doing the inout port wrong?
Also I'm rather new to VHDL, so if any of you would approach it differently please let me know.
Thanks!
Code:
ENTITY lcd_interface IS
--Add Generic
PORT (db : INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);
en, rs, rw : OUT STD_LOGIC;
-- clk : IN STD_LOGIC;
lcd_clk_tick : IN STD_LOGIC; -- REMOVE AFTER TESTING
reset : IN STD_LOGIC;
lcd_count_tick_o : OUT STD_LOGIC);
END lcd_interface;
ARCHITECTURE controller OF lcd_interface IS
TYPE STATE_TYPE IS (INIT_0, INIT_1, INIT_2, EN_H, EN_L); -- ADD EN_H??
SIGNAL state, next_state : STATE_TYPE;
SIGNAL i_en : STD_LOGIC;
SIGNAL clk_count, lcd_count : STD_LOGIC_VECTOR (9 DOWNTO 0) := "0000000000";
--SIGNAL lcd_clk_tick : STD_LOGIC;
SIGNAL db_out, db_in : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
lcd_count_tick_o <= lcd_clk_tick;
en <= i_en;
db <= db_out when i_en = '1' else (OTHERS => 'Z'); -- *FIND OUT IF THIS PART IS CORRECT!!*
db_in <= db;
-- PROCESS (reset, clk)
-- BEGIN
-- IF reset = '0' THEN
-- clk_count <= "0000000000";
-- ELSIF clk'EVENT AND clk = '1' THEN
-- IF clk_count < "1111101000" THEN -- wait 20us (clk_count = 1000)
-- clk_count <= clk_count + 1;
-- lcd_clk_tick <= '0';
-- ELSE
-- clk_count <= (OTHERS => '0');
-- lcd_clk_tick <= '1'; -- generates pulse every 20uS (50kHz)
-- END IF;
-- END IF;
-- END PROCESS;
PROCESS (reset, lcd_clk_tick)
BEGIN
IF reset = '0' THEN
lcd_count <= "0000000000";
db_out <= (OTHERS => '0'); -- data bus
i_en <= '0'; -- en = '1' starts data read/write
rs <= '0'; -- rs = reg select ('0'/'1' = instr_reg(write) / data_reg(read))
rw <= '0'; -- rw' = read/write'
state <= INIT_0;
ELSIF lcd_clk_tick'EVENT AND lcd_clk_tick = '1' THEN
CASE state IS
-- INIT SEQUENCE
WHEN INIT_0 =>
IF lcd_count < "1011101110" THEN -- wait 15ms (lcd_count = 750)
lcd_count <= lcd_count + 1;
ELSE
lcd_count <= (OTHERS => '0');
rs <= '0';
rw <= '0';
db_out <= "00110000";
state <= EN_H; -- rs and rw' need to be stable before en = 'H'
next_state <= INIT_1;
END IF;
WHEN INIT_1 =>
IF lcd_count < "00011010010" THEN -- wait 4.2ms (lcd_count = 210)
lcd_count <= lcd_count + 1;
ELSE
lcd_count <= (OTHERS => '0');
rs <= '0';
rw <= '0';
db_out <= "00110000";
state <= EN_H;
next_state <= INIT_2;
END IF;
WHEN INIT_2 =>
IF lcd_count < "00000000101" THEN -- wait 100us (lcd_count = 5)
lcd_count <= lcd_count + 1;
ELSE
lcd_count <= (OTHERS => '0');
rs <= '0';
rw <= '0';
db_out <= "00110000";
state <= EN_H;
next_state <= INIT_0;
END IF;
-- TRANSFER SEQUENCE -- change enable so it's before?? _/-------\_
WHEN EN_H =>
i_en <= '1';
state <= EN_L;
WHEN EN_L =>
IF lcd_count < "0000000001" THEN -- wait 20us
lcd_count <= lcd_count + 1;
ELSE
lcd_count <= (OTHERS => '0');
i_en <= '0';
state <= next_state;
END IF;
END CASE;
END IF;
END PROCESS;
END controller;
Last edited: