- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
this is the lcd ili9341 screen im trying to configure with VHDL for project, ill add here in the end the modules i built. i created an SPI module and ili configuration module by looking at the data sheet and inspecting another modules online, i find it dificult to configure it with the configurations i have found, also i have tried to work with lower system clk for the SCK around 10MHZ so the system would not exeed the system clock that should be maximum 24MHZ. please someone could help me find a way to configure it and explain to me the process of showing data over the screen.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ili9341_spi is
Port (
spiClk : in std_logic; -- Input clock signal for SPI timing 12Mhz
data : in std_logic_vector(8 downto 0); -- 9-bit data to be transmitted (MSB is DC flag)
dataAvailable : in std_logic; -- Indicates that new data is available for transmission
tft_sck : out std_logic; -- SPI clock output to the TFT (active only when CS is active)
tft_sdi : out std_logic; -- SPI data output to the TFT (serial data line)
tft_dc : out std_logic; -- Data/Command (DC) signal for the TFT (MSB of the data)
tft_cs : out std_logic; -- Chip Select (CS) signal for the TFT (active low)
idle : buffer std_logic := '1' -- Indicates the SPI module is idle (1 when no transmission in progress)
);
end ili9341_spi;
architecture ili9341_spi_arc of ili9341_spi is
-- Registers
signal send_index : integer range 1 to 7 := 1;
signal internalData : std_logic_vector(8 downto 0) := (others => '0');
signal cs : std_logic := '1';
-- Combinational Assignments / wires
signal dataDc : std_logic;
signal dataShift : std_logic_vector(0 to 7);
begin
-- Wires Assignments
dataDc <= internalData(8);
dataShift <= internalData(7 downto 0);
-- SPI transmit
process(spiClk)
begin
if rising_edge(spiClk) then
-- Store new data in internal register
-- Having Data and ready to transmite
if dataAvailable = '1' and idle = '1' then
internalData <= data; -- Copy new data into internal buffer
idle <= '0'; -- Start transmission
cs <= '0'; -- ili9341 selected
tft_sdi <= dataShift(0);
--end if;
-- Change data if we're actively sending
elsif idle = '0' then
-- Update Pins
tft_sdi <= dataShift(send_index);
-- Increment counter
if send_index = 7 then
send_index <= 1; -- Reset send_index after sending 8bits
idle <= '1'; -- sending last bit;
else
send_index <= send_index + 1;
end if;
-- no data to send
else
cs <= '1';
end if;
end if;
end process;
-- Assigning
tft_dc <= dataDc;
tft_sck <= spiClk and not cs; -- only drive sck with an active CS
tft_cs <= cs;
end ili9341_spi_arc;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.ili9341_pkg.all;
entity ili9341 is
Port (
clk : in std_logic; -- Input clock (e.g., 100MHz)
tft_sck : out std_logic; -- SPI clock signal
tft_sdi : out std_logic; -- SPI data output (MOSI)
tft_dc : out std_logic; -- Data/Command signal
tft_reset : out std_logic; -- Reset signal for the TFT (active low)
tft_cs : out std_logic; -- Chip Select (active low)
-- framebufferData : in std_logic_vector(15 downto 0):=x"00"; -- RGB565 data input for the frame buffer
led : out std_logic_vector(3 downto 0);
framebufferClk : out std_logic -- Framebuffer clock to synchronize data reading
);
end ili9341;
architecture ili9341_arc of ili9341 is
-- Constant
constant INPUT_CLK_MHZ : integer := 24;
-- Signals
signal spiClk : std_logic := '0'; -- Generated 10-12MHz clk
signal spi_counter_clk : integer range 0 to 10 := 0; -- Counter For spiClk
signal frameBufferLowNibble : std_logic := '1';
signal spiData : std_logic_vector(8 downto 0) := (others => '0'); -- Data to send via SPI
signal spiDataSet : std_logic := '0'; -- Indicates new data is ready
signal spiIdle : std_logic := '1'; -- Indicates SPI is idle
component ili9341_spi
Port (
spiClk : in std_logic; -- Input clock signal for SPI timing 12Mhz
data : in std_logic_vector(8 downto 0); -- 9-bit data to be transmitted (MSB is DC flag)
dataAvailable : in std_logic; -- Indicates that new data is available for transmission
tft_sck : out std_logic; -- SPI clock output to the TFT (active only when CS is active)
tft_sdi : out std_logic; -- SPI data output to the TFT (serial data line)
tft_dc : out std_logic; -- Data/Command (DC) signal for the TFT (MSB of the data)
tft_cs : out std_logic; -- Chip Select (CS) signal for the TFT (active low)
idle : buffer std_logic := '1' -- Indicates the SPI module is idle (1 when no transmission in progress)
);
end component;
-- state machine with delay + idle support (used for initialization)
signal remainingDelayTicks : integer := 0;
type state_type is ( START, HOLD_RESET, WAIT_FOR_POWERUP, SEND_INIT_SEQ, END_LOOP);
signal state : state_type := START;
signal framebufferDataS : std_logic_vector(15 downto 0) := x"F800";
signal initSeqCounter : integer range 0 to INIT_SEQ_LEN := 0;
begin
-- SPI_ILI9341 Unit
ili9341_Unit : ili9341_spi
port map (
spiClk => spiClk,
data => spiData,
dataAvailable => spiDataSet,
tft_sck => tft_sck,
tft_sdi => tft_sdi,
tft_dc => tft_dc,
tft_cs => tft_cs,
idle => spiIdle
);
spiClk_process :
process (clk)
begin
if rising_edge(clk) then
if spi_counter_clk = 10 then
spiClk <= not spiClk;
spi_counter_clk <= 0;
else
spi_counter_clk <= spi_counter_clk + 1;
end if;
end if;
end process;
process (spiClk)
begin
if rising_edge(spiClk) then
-- clear data flag first
spiDataSet <= '0';
-- always decrement delay ticks
if remainingDelayTicks > 0 then
remainingDelayTicks <= remainingDelayTicks - 1;
elsif (spiIdle and not spiDataSet) = '1' then
-- advance state machine to next state, but only do this if we
-- didn't just clock in the last byte (since idle is not yet updated)
case state is
-- initialize all pins in START mode; reset the LCD
when START =>
led <= "0001";
tft_reset <= '0';
remainingDelayTicks <= INPUT_CLK_MHZ * 100;
state <= HOLD_RESET;
-- wait for RESET to kick in; then release pin & wait for power up
when HOLD_RESET =>
led <= "0010";
tft_reset <= '1'; -- release pin
remainingDelayTicks <= INPUT_CLK_MHZ * 12000;
state <= WAIT_FOR_POWERUP;
-- if power up is completed -> sw reset
when WAIT_FOR_POWERUP =>
led <= "0100";
spiData <= COM & x"11";
spiDataSet <= '1';
remainingDelayTicks <= INPUT_CLK_MHZ * 5000;
state <= SEND_INIT_SEQ;
when SEND_INIT_SEQ =>
led <= "1000";
if initSeqCounter < INIT_SEQ_LEN then
spiData <= INIT_SEQ(initSeqCounter);
spiDataSet <= '1';
remainingDelayTicks <= 6000000;
initSeqCounter <= initSeqCounter + 1;
else
state <= END_LOOP;
end if;
when END_LOOP =>
led <= "1111";
if frameBufferLowNibble = '0' then
--spiData <= ('1' & framebufferData(15 downto 8));
spiData <= ('1' & framebufferDataS(15 downto 8));
else
--spiData <= ('1' & framebufferData(7 downto 0));
spiData <= ('1' & framebufferDataS(7 downto 0));
end if;
spiDataSet <= '1';
frameBufferLowNibble <= not frameBufferLowNibble;
end case;
end if;
end if;
end process;
-- Assigns
framebufferClk <= not frameBufferLowNibble;
end ili9341_arc;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package ili9341_pkg is
constant COM : std_logic := '0'; -- Command
constant DAT : std_logic := '1'; -- Data
constant INIT_SEQ_LEN : integer := 52;
type init_seq_array is
--array (natural range <>) of std_logic_vector(8 downto 0);
array (0 to INIT_SEQ_LEN-1) of std_logic_vector(8 downto 0);
constant INIT_SEQ : init_seq_array := (
-- Turn off Display
(COM & x"28"),
-- Init (??)
(COM & x"CF"), (DAT & x"00"), (DAT & x"83"), (DAT & x"30"),
(COM & x"ED"), (DAT & x"64"), (DAT & x"03"), (DAT & x"12"), (DAT & x"81"),
(COM & x"E8"), (DAT & x"85"), (DAT & x"01"), (DAT & x"79"),
(COM & x"CB"), (DAT & x"39"), (DAT & x"2C"), (DAT & x"00"), (DAT & x"34"), (DAT & x"02"),
(COM & x"F7"), (DAT & x"20"),
(COM & x"EA"), (DAT & x"00"), (DAT & x"00"),
-- Power Control
(COM & x"C0"), (DAT & x"26"),
(COM & x"C1"), (DAT & x"11"),
--VCOM
(COM & x"C5"), (DAT & x"35"), (DAT & x"3E"),
(COM & x"C7"), (DAT & x"BE"),
-- Memory Access Control
(COM & x"3A"), (DAT & x"55"),
-- Frame Rate
(COM & x"B1"), (DAT & x"00"), (DAT & x"1B"),
-- Gamma
(COM & x"26"), (DAT & x"01"),
-- Brightness
(COM & x"51"), (DAT & x"FF"),
-- Display
(COM & x"B7"), (DAT & x"07"),
(COM & x"B6"), (DAT & x"0A"), (DAT & x"82"), (DAT & x"27"), (DAT & x"00"),
(COM & x"29"), -- Enable Display
(COM & x"2C") -- Start Memory-Write
);
end package ili9341_pkg;
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Is this module from other vendor? If yes, I think you need to get the design example from that vendor.
Thanks,
Regards,
Sheng
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I won't expect that someone is willing to review your code unless they are already involved with ili9341. Most driver solutions are uC based, I noticed however a Verilog ili9341 driver project at Github. I'd start from there.
I won't expect that someone is willing to review your code unless they are already involved with ili9341. Most driver solutions are uC based, I noticed however a Verilog ili9341 driver project at Github. I'd start from there.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page