Disabled external gits
This commit is contained in:
188
cs473-es/lab3/hw/hdl/LCDController/LCDDriver.vhd
Normal file
188
cs473-es/lab3/hw/hdl/LCDController/LCDDriver.vhd
Normal file
@@ -0,0 +1,188 @@
|
||||
-- altera vhdl_input_version vhdl_2008
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
entity LCDDriver is
|
||||
generic (
|
||||
F_CLK : natural -- Board frequency in Hz
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
|
||||
data_in : in std_logic_vector(15 downto 0);
|
||||
empty_in : in std_logic;
|
||||
refresh_in : in std_logic;
|
||||
|
||||
cmd_en_in : in std_logic;
|
||||
cmd_dcx_in : in std_logic;
|
||||
cmd_data_in : in std_logic_vector(7 downto 0);
|
||||
|
||||
data_out : out std_logic_vector(15 downto 0);
|
||||
rd_n : out std_logic;
|
||||
wr_n : out std_logic;
|
||||
rs : out std_logic;
|
||||
cs_n : out std_logic;
|
||||
|
||||
lcd_rdreq : out std_logic;
|
||||
|
||||
busy : out std_logic
|
||||
);
|
||||
end LCDDriver;
|
||||
|
||||
architecture Behavioral of LCDDriver is
|
||||
|
||||
constant F_LCD : natural := natural(real(25)*10**(6.0));
|
||||
constant F_LCD_MIN : natural := natural(real(12.5)*10**(6.0));
|
||||
constant F_LCD_MAX : natural := natural(real(30)*10**(6.0));
|
||||
|
||||
constant lcd_clk_en : std_logic := '1' ;
|
||||
signal lcd_clk : std_logic;
|
||||
|
||||
type GState is (tx, cmd, ready, std_wait,cmd_wait);
|
||||
type SNDState is (init, wrx, tx, done);
|
||||
|
||||
signal snds_reg, snds_next : SNDState;
|
||||
signal gs_reg, gs_next : GState;
|
||||
|
||||
signal data_reg : std_logic_vector(15 downto 0);
|
||||
|
||||
signal cmd_dcx_reg : std_logic := '1';
|
||||
signal cmd_data_reg : std_logic_vector(7 downto 0);
|
||||
|
||||
signal rdreq_limiter : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
busy <= '0' when gs_reg = ready else '1';
|
||||
|
||||
--Global State Process
|
||||
process (all) begin
|
||||
gs_next <= gs_reg;
|
||||
snds_next <= snds_reg;
|
||||
|
||||
case gs_reg is
|
||||
when ready =>
|
||||
if cmd_en_in = '1' then
|
||||
if lcd_clk = '1' then
|
||||
gs_next <= cmd;
|
||||
snds_next <= wrx;
|
||||
else
|
||||
gs_next <= cmd_wait;
|
||||
end if;
|
||||
elsif refresh_in = '1' then
|
||||
gs_next <= std_wait;
|
||||
end if;
|
||||
when cmd_wait =>
|
||||
if lcd_clk = '1' then
|
||||
gs_next <= cmd;
|
||||
snds_next <= wrx;
|
||||
end if;
|
||||
when std_wait =>
|
||||
if empty_in = '0' then
|
||||
if lcd_clk = '1' then
|
||||
gs_next <= tx;
|
||||
snds_next <= init;
|
||||
end if;
|
||||
end if;
|
||||
when tx =>
|
||||
if snds_reg = done then
|
||||
gs_next <= ready;
|
||||
end if;
|
||||
when cmd =>
|
||||
if snds_reg = done then
|
||||
gs_next <= ready;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
if (gs_reg = cmd or gs_reg = tx) then
|
||||
case snds_reg is
|
||||
when wrx =>
|
||||
snds_next <= tx;
|
||||
when tx =>
|
||||
if gs_reg = cmd then
|
||||
snds_next <= done;
|
||||
elsif gs_reg = tx then
|
||||
if empty_in = '1' then
|
||||
snds_next <= done;
|
||||
else
|
||||
snds_next <= wrx;
|
||||
end if;
|
||||
end if;
|
||||
when init =>
|
||||
snds_next <= wrx;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
rs <= cmd_dcx_reg when gs_reg = cmd else '1'; -- DCX when CMD else Keep high
|
||||
cs_n <= not rst_n; -- Chip Select
|
||||
wr_n <= '0' when (gs_reg = cmd or gs_reg = tx) and
|
||||
snds_reg = wrx else '1'; -- Write data on rising edge
|
||||
rd_n <= '1'; -- Unused, Read data on rising edge
|
||||
|
||||
data_out <= data_reg when gs_reg = tx else
|
||||
"00000000" & cmd_data_reg when gs_reg = cmd else
|
||||
(others => '0');
|
||||
|
||||
lcd_rdreq <= '1' when (gs_reg = ready and gs_next = std_wait) or
|
||||
(snds_reg /= init and snds_next = init) or
|
||||
(rdreq_limiter = '0' and gs_reg = tx and snds_reg = tx) else '0';
|
||||
|
||||
-- Clock Sync & State Handler
|
||||
process (clk, rst_n) begin
|
||||
if rst_n = '0' then
|
||||
gs_reg <= ready;
|
||||
snds_reg <= wrx;
|
||||
|
||||
data_reg <= (others => '0');
|
||||
|
||||
cmd_dcx_reg <= '0';
|
||||
cmd_data_reg <= (others => '0');
|
||||
elsif rising_edge(clk) then
|
||||
|
||||
gs_reg <= gs_next;
|
||||
if lcd_clk = '1' then
|
||||
snds_reg <= snds_next; -- We run the SND at 25Mhz to respect state timings
|
||||
|
||||
if (snds_reg = tx or snds_reg = init) then
|
||||
data_reg <= data_in;
|
||||
end if;
|
||||
if (snds_reg = wrx) then
|
||||
rdreq_limiter <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if lcd_rdreq = '1' then
|
||||
rdreq_limiter <= '1';
|
||||
end if;
|
||||
|
||||
if gs_reg = ready and (cmd_en_in = '1') then
|
||||
cmd_dcx_reg <= cmd_dcx_in;
|
||||
cmd_data_reg <= cmd_data_in;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- WS output clock
|
||||
clkgen_ent : entity work.ClkGen
|
||||
generic map (
|
||||
F_CLK => F_CLK,
|
||||
F_OUT => integer(F_LCD),
|
||||
F_MIN => integer(F_LCD_MIN),
|
||||
F_MAX => integer(F_LCD_MAX)
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
rst_n => rst_n,
|
||||
clk_o => lcd_clk,
|
||||
en => lcd_clk_en
|
||||
);
|
||||
|
||||
|
||||
end Behavioral;
|
Reference in New Issue
Block a user