Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@ -0,0 +1,43 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity ClkGen is
generic (
F_CLK : natural; -- Hz
F_OUT : natural; -- Hz
F_MIN : natural; -- Hz
F_MAX : natural -- Hz
);
port (
clk : in std_logic;
rst_n : in std_logic;
clk_o : out std_logic;
en : in std_logic
);
end ClkGen;
architecture Behavioral of ClkGen is
constant CNT_MAX : integer := integer(floor(real(F_CLK) / real(F_OUT))) - 1;
constant F_ACTUAL : integer := (F_CLK/natural(CNT_MAX+1));
signal counter_reg, counter_next: integer range CNT_MAX downto 0;
begin
assert F_MIN <= F_ACTUAL report "Invalid Timings for ClkGen ("&integer'image(F_ACTUAL)&"hz < "&integer'image(F_MIN)&"hz)" severity error;
assert F_MAX >= F_ACTUAL report "Invalid Timings for ClkGen ("&integer'image(F_ACTUAL)&"hz > "&integer'image(F_MAX)&"hz)" severity error;
assert F_MIN <= F_OUT and F_OUT <= F_MAX report "Invalid Timings for ClkGen (F_MIN<=F_OUT<=F_MAX)." severity error;
counter_next <= CNT_MAX when counter_reg = 0 else counter_reg - 1;
process(clk, rst_n) begin
if rising_edge(clk) then
if rst_n = '0' then
counter_reg <= CNT_MAX;
else
if en = '1' then
counter_reg <= counter_next;
end if;
end if;
end if;
end process;
clk_o <= '1' when counter_reg = 0 and en = '1' else '0';
end Behavioral; -- Behavioral

View File

@ -0,0 +1,136 @@
-- 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 LCDAvalonMaster is
generic (
NWORDS_MAX : natural
);
port (
clk : in std_logic;
rst_n : in std_logic;
waitreq : in std_logic;
readdata : in std_logic_vector(31 downto 0);
readdatavalid : in std_logic;
address : out std_logic_vector(31 downto 0);
burstcount : out std_logic_vector(4 downto 0);
am_read : out std_logic;
refresh : in std_logic;
fifo_almost_empty : in std_logic;
fifo_data : out std_logic_vector(31 downto 0);
fifo_wr_req : out std_logic;
baseaddress : in std_logic_vector(31 downto 0);
nwords : in std_logic_vector(integer(ceil(log2(real(NWORDS_MAX)))) downto 0)
);
end LCDAvalonMaster;
architecture behavioral of LCDAvalonMaster is
-- Generic constants
constant BURST_COUNT : integer := 16;
constant BURST_COUNT_SLV : std_logic_vector(burstcount'left downto 0) := std_logic_vector(to_unsigned(BURST_COUNT, burstcount'length));
-- Type definitions
type State is (S_READY, S_BURSTREQ, S_BURSTRD, S_FIFOWAIT);
subtype BurstCounter is integer range 0 to BURST_COUNT;
subtype WordCounter is integer range 0 to NWORDS_MAX;
-- Inferred registers
signal rdaddr_reg, rdaddr_next : std_logic_vector(31 downto 0);
signal state_reg, state_next : State;
signal burstcnt_reg, burstcnt_next : BurstCounter; -- Counts # of words read during a single burst
signal wordcnt_reg, wordcnt_next : WordCounter; -- Counts # of words read during a refresh cycle
begin
-- PROCESS state machine
process(all) begin
state_next <= state_reg;
rdaddr_next <= rdaddr_reg;
burstcnt_next <= burstcnt_reg;
wordcnt_next <= wordcnt_reg;
-- Avalon master default output signals
burstcount <= BURST_COUNT_SLV;
am_read <= '0';
case state_reg is
when S_READY =>
-- ====================== AM STATE: READY ======================
if refresh = '1' then
wordcnt_next <= integer(to_integer(unsigned(nwords)));
state_next <= S_BURSTREQ;
end if;
when S_BURSTREQ =>
-- ================== AM STATE: BURST REQUEST ==================
am_read <= '1';
if waitreq = '0' then
-- Burst was accepted,
state_next <= S_BURSTRD;
-- Calculate the # of words we plan to read during this burst
-- and update counters accordingly.
if wordcnt_reg < BURST_COUNT then
burstcnt_next <= wordcnt_reg;
wordcnt_next <= 0;
else
burstcnt_next <= BURST_COUNT;
wordcnt_next <= wordcnt_reg - BURST_COUNT;
end if;
end if;
when S_BURSTRD =>
-- ==================== AM STATE: BURST READ ===================
if readdatavalid = '1' then
if burstcnt_reg = 1 then
-- Got last word, burst read finished
if wordcnt_reg = 0 then
-- All nwords read
state_next <= S_READY;
else
-- < nwords read
state_next <= S_FIFOWAIT;
end if;
else
burstcnt_next <= burstcnt_reg - 1;
end if;
end if;
when S_FIFOWAIT =>
-- ==================== AM STATE: FIFO WAIT ====================
-- Await the assertion of fifo_almost_empty until reinitiating a
-- burst read
if fifo_almost_empty = '1' then
state_next <= S_BURSTREQ;
end if;
end case;
end process;
-- FIFO data transfer routing
fifo_wr_req <= '1' when state_reg = S_BURSTRD and readdatavalid = '1' else '0';
fifo_data <= readdata when state_reg = S_BURSTRD else (others => 'Z');
address <= std_logic_vector(unsigned(baseaddress) + resize((unsigned(nwords) - wordcnt_reg) * 4, address'length)) when state_reg = S_BURSTREQ else (others => 'Z');
-- Clocking process/register inferrence
process(clk) begin
if rising_edge(clk) then
if rst_n = '0' then
rdaddr_reg <= (others => '0');
state_reg <= S_READY;
burstcnt_reg <= BURST_COUNT;
wordcnt_reg <= 0;
else
rdaddr_reg <= rdaddr_next;
state_reg <= state_next;
burstcnt_reg <= burstcnt_next;
wordcnt_reg <= wordcnt_next;
end if;
end if;
end process;
end behavioral;

View File

@ -0,0 +1,108 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity LCDAvalonMaster_tb is
end LCDAvalonMaster_tb;
architecture test of LCDAvalonMaster_tb is
constant CLK_PERIOD : time := 20 ns;
constant N_LED_MAX : integer := 255;
-- 20 = 1 full burst + 1 non full burst
constant NWORDS : natural := 20;
constant NWORDS_MAX :natural := (320*240)/2;
signal clk : std_logic := '0';
signal rst_n : std_logic;
signal waitreq, readdatavalid, refresh, fifo_almost_empty : std_logic;
signal readdata : std_logic_vector(31 downto 0);
signal baseaddress : std_logic_vector(31 downto 0);
signal nwords_sig : std_logic_vector(integer(floor(log2(real(NWORDS_MAX)))) downto 0);
begin
nwords_sig <= std_logic_vector(to_unsigned(NWORDS, nwords_sig'length));
-- Instantiate DUT
dut : entity work.LCDAvalonMaster
generic map (
NWORDS_MAX => NWORDS_MAX
)
port map(
clk => clk,
rst_n => rst_n,
waitreq => waitreq,
readdatavalid => readdatavalid,
refresh => refresh,
fifo_almost_empty => fifo_almost_empty,
readdata => readdata,
baseaddress => baseaddress,
nwords => nwords_sig
);
-- Clocking process
clk_generation : process
begin
clk <= not clk;
wait for CLK_PERIOD / 2;
end process;
-- Testbench
tb : process
begin
while true loop
-- Dummy signals from bus
readdata <= X"12341234";
readdatavalid <= '0';
waitreq <= '1';
baseaddress <= X"10000000";
fifo_almost_empty <= '0';
-- Reset
rst_n <= '0';
wait for CLK_PERIOD * 2.5;
rst_n <= '1';
wait for CLK_PERIOD * 2;
-- Initiate a refresh cycle
wait until rising_edge(clk);
refresh <= '1';
wait for CLK_PERIOD;
refresh <= '0';
-- Wait until bus grant
wait for CLK_PERIOD * 3;
waitreq <= '0';
wait for CLK_PERIOD;
-- Emulate that new read data is valid each cycle of the burst
readdatavalid <= '1';
for i in 1 to 16 loop
wait for CLK_PERIOD;
end loop;
readdatavalid <= '0';
wait for CLK_PERIOD * 5;
-- Assert fifo_almost empty; should repromt another transfer
fifo_almost_empty <= '1';
wait for CLK_period;
fifo_almost_empty <= '0';
wait for CLK_PERIOD * 2;
readdatavalid <= '1';
for i in 1 to 16 loop
wait for CLK_PERIOD;
end loop;
-- Test finished
wait for CLK_PERIOD * 5;
end loop;
end process;
end;

View File

@ -0,0 +1,370 @@
-- altera vhdl_input_version vhdl_2008
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
LIBRARY altera_mf;
use altera_mf.altera_mf_components.all;
entity LCDController is
port(
clk : in std_logic;
rst_n : in std_logic;
-- Avalon slave interface
avalon_slave_address : in std_logic_vector (3 downto 0);
avalon_slave_write : in std_logic;
avalon_slave_writedata : in std_logic_vector(31 downto 0);
avalon_slave_read : in std_logic;
avalon_slave_readdata : out std_logic_vector(31 downto 0);
avalon_slave_waitrequest : out std_logic;
av_irq : out std_logic;
-- Avalon master interface
avalon_master_waitreq : in std_logic;
avalon_master_readdata : in std_logic_vector(31 downto 0);
avalon_master_readdatavalid : in std_logic;
avalon_master_address : out std_logic_vector(31 downto 0);
avalon_master_burstcount : out std_logic_vector(4 downto 0);
avalon_master_read : out std_logic;
-- LT24 conduit interface
lt24_rd_n : out std_logic;
lt24_wr_n : out std_logic;
lt24_rs : out std_logic;
lt24_cs_n : out std_logic;
lt24_data : out std_logic_vector(15 downto 0);
lt24_reset_n : out std_logic;
lt24_lcd_on : out std_logic
);
end LCDController;
architecture comp of LCDController is
-- Type definitions
type State is (S_READY, S_REFRESHING);
type IRQ_CTRL is record
enabled : boolean;
clear_on_refresh : boolean;
irq0_active : std_logic;
end record IRQ_CTRL;
-- Generic constants
constant F_CLK : natural := 50*10**6;
constant ZERO_ADDR : std_logic_vector(31 downto 0) := (others => '0');
constant MAX_H : natural := 240;
constant MAX_W : natural := 320;
constant N_PIXELS : natural := MAX_H * MAX_W;
constant PIXEL_WIDTH : natural := 16;
constant AVM_BURST_LEN : natural := 256;
constant IRQ_CTRL_DEFAULT : IRQ_CTRL := (
enabled => true,
clear_on_refresh => true,
irq0_active => '0'
);
-- Avalon slave programmable interface constants
constant A_WRITEREG : natural := 0;
constant A_WRITEDATA : natural := 1;
constant A_WRITEBASE : natural := 2;
constant A_REFRESH : natural := 3;
constant A_SETENABLED : natural := 4;
constant A_SETHEIGHT : natural := 5;
constant A_SETWIDTH : natural := 6;
constant A_WRITEIRQ : natural := 7;
constant A_SETIRQ : natural := 8;
constant A_CLEARIRQ : natural := 9;
constant A_ISBUSY : natural := 10;
constant LAST_avalon_slave_ADDR : natural := A_ISBUSY;
signal avalon_slave_address_int : integer range 0 to LAST_avalon_slave_ADDR;
-- FIFO configuration parameters
constant FIFO_N_ALMOST_EMPTY : natural := 32;
constant FIFO_WIDTH : natural := 32;
constant FIFO_SIZE : natural := AVM_BURST_LEN + FIFO_N_ALMOST_EMPTY;
constant PIXELS_PER_WORD : natural := FIFO_WIDTH / PIXEL_WIDTH;
constant NWORDS_MAX : natural := N_PIXELS / PIXELS_PER_WORD;
-- FIFO signals
signal fifo_almost_empty : std_logic;
signal fifo_wr_req : std_logic;
signal fifo_data_in, fifo_data_out : std_logic_vector(FIFO_WIDTH - 1 downto 0);
signal fifo_rd_req : std_logic;
signal fifo_empty : std_logic;
-- Inferred registers
signal baseaddr_reg, baseaddr_next : std_logic_vector(31 downto 0);
signal state_reg, state_next : State;
signal lcd_on_reg, lcd_on_next : std_logic := '1';
signal lcd_rst_reg, lcd_rst_next : std_logic := '0';
signal width_reg, width_next : integer range 0 to MAX_W;
signal height_reg, height_next : integer range 0 to MAX_H;
signal irq_ctrl_reg, irq_ctrl_next : IRQ_CTRL;
-- LCD Driver interfacing signals
signal lcd_cmd_en : std_logic;
signal lcd_cmd_dcx : std_logic;
signal lcd_cmd_data : std_logic_vector(7 downto 0);
signal lcd_busy : std_logic;
signal lcd_req : std_logic;
signal lcd_data : std_logic_vector(15 downto 0);
signal lcd_empty : std_logic;
-- LCDController state signals
signal refresh : std_logic;
-- # of words required by the fifo to gather all pixels in an image based on
-- current width and height values
signal av_nwords : std_logic_vector(integer(ceil(log2(real(NWORDS_MAX)))) downto 0);
function writeIRQCtrl(v : in std_logic_vector(2 downto 0)) return IRQ_CTRL is
variable res : IRQ_CTRL;
begin
res.enabled := v(0) = '1';
res.clear_on_refresh := v(1) = '1';
res.irq0_active := v(2);
return res;
end writeIRQCtrl;
function setIRQCtrl(current: in IRQ_CTRL; v : in std_logic_vector(2 downto 0)) return IRQ_CTRL is
variable res : IRQ_CTRL;
begin
res := current;
res.enabled := current.enabled or v(0) = '1';
res.clear_on_refresh := current.clear_on_refresh or v(1) = '1';
res.irq0_active := current.irq0_active or v(2);
return res;
end setIRQCtrl;
function clearIRQCtrl(current: in IRQ_CTRL; v : in std_logic_vector(2 downto 0)) return IRQ_CTRL is
variable res : IRQ_CTRL;
begin
res := current;
res.enabled := current.enabled and not v(0) = '1';
res.clear_on_refresh := current.clear_on_refresh and not v(1) = '1';
res.irq0_active := current.irq0_active and not v(2);
return res;
end clearIRQCtrl;
--Component declaration, required for altera library IP
component scfifo
generic (
almost_empty_value : natural;
lpm_numwords : natural;
lpm_width : natural;
lpm_widthu : natural
);
port(
aclr : in std_logic;
almost_empty : out std_logic;
clock : in std_logic;
data : in std_logic_vector(lpm_width-1 downto 0);
empty : out std_logic;
q : out std_logic_vector(lpm_width-1 downto 0);
rdreq : in std_logic;
sclr : in std_logic;
wrreq : in std_logic
);
end component;
begin
-- ENTITY LCDDriver:
lcddriver_ent : entity work.LCDDriver
generic map (
F_CLK => F_CLK
)
port map (
clk => clk,
rst_n => rst_n,
data_in => lcd_data,
empty_in => lcd_empty,
refresh_in => refresh,
cmd_en_in => lcd_cmd_en,
cmd_dcx_in => lcd_cmd_dcx,
cmd_data_in => lcd_cmd_data,
data_out => lt24_data,
rd_n => lt24_rd_n,
wr_n => lt24_wr_n,
rs => lt24_rs,
cs_n => lt24_cs_n,
lcd_rdreq => lcd_req,
busy => lcd_busy
);
-- ENTITY PixTrans:
pixtrans_ent : entity work.PixTrans
generic map (
MAX_H => MAX_H,
MAX_W => MAX_W
)
port map (
clk => clk,
rst_n => rst_n,
lcd_req => lcd_req,
data => lcd_data,
empty => lcd_empty,
fifo_req => fifo_rd_req,
fifo_q => fifo_data_out,
fifo_empty => fifo_empty,
w => width_reg,
h => height_reg
);
-- ENTITY Avalon master:
avalon_master_ent : entity work.LCDAvalonMaster
generic map (
NWORDS_MAX => NWORDS_MAX
)
port map (
clk => clk,
rst_n => rst_n,
waitreq => avalon_master_waitreq,
readdata => avalon_master_readdata,
readdatavalid => avalon_master_readdatavalid,
address => avalon_master_address,
burstcount => avalon_master_burstcount,
am_read => avalon_master_read,
refresh => refresh,
fifo_almost_empty => fifo_almost_empty,
fifo_data => fifo_data_in,
fifo_wr_req => fifo_wr_req,
baseaddress => baseaddr_reg,
nwords => av_nwords
);
-- ENTITY FIFO
fifo_ent : scfifo
generic map (
lpm_widthu => 9,
lpm_width => FIFO_WIDTH,
lpm_numwords => FIFO_SIZE,
almost_empty_value => FIFO_N_ALMOST_EMPTY
)
port map (
clock => clk,
data => fifo_data_in,
q => fifo_data_out,
wrreq => fifo_wr_req,
rdreq => fifo_rd_req,
empty => fifo_empty,
almost_empty => fifo_almost_empty,
sclr => not rst_n,
aclr => '0'
);
-- PROCESS Avalon slave interface
avalon_slave_address_int <= to_integer(unsigned(avalon_slave_address));
process(all) begin
state_next <= state_reg;
height_next <= height_reg;
width_next <= width_reg;
irq_ctrl_next <= irq_ctrl_reg;
refresh <= '0';
lcd_cmd_en <= '0';
lcd_cmd_dcx <= '0';
baseaddr_next <= baseaddr_reg;
lcd_on_next <= lcd_on_reg;
lcd_rst_next <= lcd_rst_reg;
avalon_slave_readdata <= (others => 'Z');
-- Avalon slave interface
if avalon_slave_write = '1' then
case avalon_slave_address_int is
when A_WRITEREG =>
lcd_cmd_en <= '1';
lcd_cmd_dcx <= '0';
when A_WRITEDATA =>
lcd_cmd_en <= '1';
lcd_cmd_dcx <= '1';
when A_WRITEBASE =>
baseaddr_next <= avalon_slave_writedata;
when A_REFRESH =>
if state_reg = S_READY then
refresh <= '1';
state_next <= S_REFRESHING;
if irq_ctrl_reg.clear_on_refresh then
irq_ctrl_next.irq0_active <= '0';
end if;
end if;
when A_SETENABLED =>
lcd_on_next <= avalon_slave_writedata(0);
lcd_rst_next <= avalon_slave_writedata(1);
when A_SETHEIGHT =>
height_next <= to_integer(unsigned(avalon_slave_writedata));
when A_SETWIDTH =>
width_next <= to_integer(unsigned(avalon_slave_writedata));
when A_WRITEIRQ =>
irq_ctrl_next <= writeIRQCtrl(avalon_slave_writedata(2 downto 0));
when A_SETIRQ =>
irq_ctrl_next <= setIRQCtrl(irq_ctrl_reg, avalon_slave_writedata(2 downto 0));
when A_CLEARIRQ =>
irq_ctrl_next <= clearIRQCtrl(irq_ctrl_reg, avalon_slave_writedata(2 downto 0));
when others => null;
end case;
end if;
if avalon_slave_read = '1' then
case avalon_slave_address_int is
when A_ISBUSY =>
avalon_slave_readdata <= (avalon_slave_readdata'left downto 1 => '0') & lcd_busy;
when others =>
null;
end case;
end if;
-- LCD Controller state handling
if (state_reg = S_REFRESHING) and lcd_busy = '0' then
state_next <= S_READY;
if irq_ctrl_reg.enabled then
irq_ctrl_next.irq0_active <= '1'; -- register that we are now finished
end if;
end if;
end process;
av_irq <= irq_ctrl_reg.irq0_active;
-- LCDController top level signals and functional units
lcd_cmd_data <= avalon_slave_writedata(7 downto 0);
av_nwords <= std_logic_vector(to_unsigned((height_reg * width_reg) / 2, av_nwords'length));
-- Output logic
lt24_reset_n <= not lcd_rst_reg;
lt24_lcd_on <= lcd_on_reg;
avalon_slave_waitrequest <= '1' when (lcd_busy='1' or state_reg /= S_READY) else '0';
-- Clocking process/register inferrence
process(clk) begin
if rising_edge(clk) then
if rst_n = '0' then
baseaddr_reg <= (others => '0');
state_reg <= S_READY;
height_reg <= MAX_H;
width_reg <= MAX_W;
irq_ctrl_reg <= IRQ_CTRL_DEFAULT;
lcd_on_reg <= '1';
else
state_reg <= state_next;
baseaddr_reg <= baseaddr_next;
height_reg <= height_next;
width_reg <= width_next;
irq_ctrl_reg <= irq_ctrl_next;
lcd_on_reg <= lcd_on_next;
lcd_rst_reg <= lcd_rst_next;
end if;
end if;
end process;
end comp;

View File

@ -0,0 +1,199 @@
# TCL File Generated by Component Editor 18.1
# Wed Jan 06 17:21:08 CET 2021
# DO NOT MODIFY
#
# LCDController "LCDController" v1.0
# 2021.01.06.17:21:08
#
#
#
# request TCL package from ACDS 16.1
#
package require -exact qsys 16.1
#
# module LCDController
#
set_module_property DESCRIPTION ""
set_module_property NAME LCDController
set_module_property VERSION 1.0
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property AUTHOR ""
set_module_property DISPLAY_NAME LCDController
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE true
set_module_property REPORT_TO_TALKBACK false
set_module_property ALLOW_GREYBOX_GENERATION false
set_module_property REPORT_HIERARCHY false
#
# file sets
#
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" ""
set_fileset_property QUARTUS_SYNTH TOP_LEVEL LCDController
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false
add_fileset_file LCDController.vhd VHDL PATH LCDController.vhd TOP_LEVEL_FILE
add_fileset_file ClkGen.vhd VHDL PATH ClkGen.vhd
add_fileset_file LCDAvalonMaster.vhd VHDL PATH LCDAvalonMaster.vhd
add_fileset_file LCDDriver.vhd VHDL PATH LCDDriver.vhd
add_fileset_file PixTrans.vhd VHDL PATH PixTrans.vhd
#
# parameters
#
#
# display items
#
#
# connection point avalon_slave
#
add_interface avalon_slave avalon end
set_interface_property avalon_slave addressUnits WORDS
set_interface_property avalon_slave associatedClock clock_sink
set_interface_property avalon_slave associatedReset reset_sink
set_interface_property avalon_slave bitsPerSymbol 8
set_interface_property avalon_slave burstOnBurstBoundariesOnly false
set_interface_property avalon_slave burstcountUnits WORDS
set_interface_property avalon_slave explicitAddressSpan 0
set_interface_property avalon_slave holdTime 0
set_interface_property avalon_slave linewrapBursts false
set_interface_property avalon_slave maximumPendingReadTransactions 0
set_interface_property avalon_slave maximumPendingWriteTransactions 0
set_interface_property avalon_slave readLatency 0
set_interface_property avalon_slave readWaitStates 0
set_interface_property avalon_slave readWaitTime 0
set_interface_property avalon_slave setupTime 0
set_interface_property avalon_slave timingUnits Cycles
set_interface_property avalon_slave writeWaitTime 0
set_interface_property avalon_slave ENABLED true
set_interface_property avalon_slave EXPORT_OF ""
set_interface_property avalon_slave PORT_NAME_MAP ""
set_interface_property avalon_slave CMSIS_SVD_VARIABLES ""
set_interface_property avalon_slave SVD_ADDRESS_GROUP ""
add_interface_port avalon_slave avalon_slave_address address Input 4
add_interface_port avalon_slave avalon_slave_write write Input 1
add_interface_port avalon_slave avalon_slave_writedata writedata Input 32
add_interface_port avalon_slave avalon_slave_read read Input 1
add_interface_port avalon_slave avalon_slave_readdata readdata Output 32
add_interface_port avalon_slave avalon_slave_waitrequest waitrequest Output 1
set_interface_assignment avalon_slave embeddedsw.configuration.isFlash 0
set_interface_assignment avalon_slave embeddedsw.configuration.isMemoryDevice 0
set_interface_assignment avalon_slave embeddedsw.configuration.isNonVolatileStorage 0
set_interface_assignment avalon_slave embeddedsw.configuration.isPrintableDevice 0
#
# connection point clock_sink
#
add_interface clock_sink clock end
set_interface_property clock_sink clockRate 0
set_interface_property clock_sink ENABLED true
set_interface_property clock_sink EXPORT_OF ""
set_interface_property clock_sink PORT_NAME_MAP ""
set_interface_property clock_sink CMSIS_SVD_VARIABLES ""
set_interface_property clock_sink SVD_ADDRESS_GROUP ""
add_interface_port clock_sink clk clk Input 1
#
# connection point reset_sink
#
add_interface reset_sink reset end
set_interface_property reset_sink associatedClock clock_sink
set_interface_property reset_sink synchronousEdges DEASSERT
set_interface_property reset_sink ENABLED true
set_interface_property reset_sink EXPORT_OF ""
set_interface_property reset_sink PORT_NAME_MAP ""
set_interface_property reset_sink CMSIS_SVD_VARIABLES ""
set_interface_property reset_sink SVD_ADDRESS_GROUP ""
add_interface_port reset_sink rst_n reset_n Input 1
#
# connection point avalon_master
#
add_interface avalon_master avalon start
set_interface_property avalon_master addressUnits SYMBOLS
set_interface_property avalon_master associatedClock clock_sink
set_interface_property avalon_master associatedReset reset_sink
set_interface_property avalon_master bitsPerSymbol 8
set_interface_property avalon_master burstOnBurstBoundariesOnly false
set_interface_property avalon_master burstcountUnits WORDS
set_interface_property avalon_master doStreamReads false
set_interface_property avalon_master doStreamWrites false
set_interface_property avalon_master holdTime 0
set_interface_property avalon_master linewrapBursts false
set_interface_property avalon_master maximumPendingReadTransactions 0
set_interface_property avalon_master maximumPendingWriteTransactions 0
set_interface_property avalon_master readLatency 0
set_interface_property avalon_master readWaitTime 1
set_interface_property avalon_master setupTime 0
set_interface_property avalon_master timingUnits Cycles
set_interface_property avalon_master writeWaitTime 0
set_interface_property avalon_master ENABLED true
set_interface_property avalon_master EXPORT_OF ""
set_interface_property avalon_master PORT_NAME_MAP ""
set_interface_property avalon_master CMSIS_SVD_VARIABLES ""
set_interface_property avalon_master SVD_ADDRESS_GROUP ""
add_interface_port avalon_master avalon_master_address address Output 32
add_interface_port avalon_master avalon_master_burstcount burstcount Output 5
add_interface_port avalon_master avalon_master_read read Output 1
add_interface_port avalon_master avalon_master_readdata readdata Input 32
add_interface_port avalon_master avalon_master_readdatavalid readdatavalid Input 1
add_interface_port avalon_master avalon_master_waitreq waitrequest Input 1
#
# connection point irq
#
add_interface irq interrupt end
set_interface_property irq associatedAddressablePoint avalon_slave
set_interface_property irq associatedClock clock_sink
set_interface_property irq associatedReset reset_sink
set_interface_property irq bridgedReceiverOffset ""
set_interface_property irq bridgesToReceiver ""
set_interface_property irq ENABLED true
set_interface_property irq EXPORT_OF ""
set_interface_property irq PORT_NAME_MAP ""
set_interface_property irq CMSIS_SVD_VARIABLES ""
set_interface_property irq SVD_ADDRESS_GROUP ""
add_interface_port irq av_irq irq Output 1
#
# connection point LT24
#
add_interface LT24 conduit end
set_interface_property LT24 associatedClock clock_sink
set_interface_property LT24 associatedReset reset_sink
set_interface_property LT24 ENABLED true
set_interface_property LT24 EXPORT_OF ""
set_interface_property LT24 PORT_NAME_MAP ""
set_interface_property LT24 CMSIS_SVD_VARIABLES ""
set_interface_property LT24 SVD_ADDRESS_GROUP ""
add_interface_port LT24 lt24_cs_n cs_n Output 1
add_interface_port LT24 lt24_data data Output 16
add_interface_port LT24 lt24_lcd_on lcd_on Output 1
add_interface_port LT24 lt24_rd_n rd_n Output 1
add_interface_port LT24 lt24_reset_n reset_n Output 1
add_interface_port LT24 lt24_rs rs Output 1
add_interface_port LT24 lt24_wr_n wr_n Output 1

View File

@ -0,0 +1,142 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use std.env.finish;
entity LCDController_tb is
end LCDController_tb;
architecture test of LCDController_tb is
constant CLK_PERIOD : time := 20 ns;
signal clk : std_logic := '0';
signal rst_n : std_logic;
signal waitreq, readdatavalid, fifo_almost_empty : std_logic;
-- Avalon slave interface
signal avalon_slave_address : std_logic_vector (3 downto 0);
signal avalon_slave_write : std_logic;
signal avalon_slave_writedata : std_logic_vector(31 downto 0);
signal avalon_slave_read : std_logic;
signal avalon_slave_readdata : std_logic_vector(31 downto 0);
-- Avalon master interface
signal avalon_master_waitreq : std_logic;
signal avalon_master_readdata : std_logic_vector(31 downto 0);
signal avalon_master_readdatavalid : std_logic;
signal avalon_master_read : std_logic;
signal irq : std_logic;
begin
-- Instantiate DUT
dut : entity work.LCDController
port map(
clk => clk,
rst_n => rst_n,
av_irq => irq,
avalon_slave_address => avalon_slave_address,
avalon_slave_write => avalon_slave_write,
avalon_slave_writedata => avalon_slave_writedata,
avalon_slave_read => avalon_slave_read,
avalon_slave_readdata => avalon_slave_readdata,
avalon_master_waitreq => avalon_master_waitreq,
avalon_master_readdata => avalon_master_readdata,
avalon_master_readdatavalid => avalon_master_readdatavalid,
avalon_master_read => avalon_master_read
);
-- Clocking process
clk_generation : process
begin
clk <= not clk;
wait for CLK_PERIOD / 2;
end process;
-- Testbench
tb : process
begin
avalon_slave_address <= "0011";
avalon_slave_write <= '0';
avalon_slave_writedata <= (others => 'Z');
-- Dummy signals from bus
avalon_master_readdata <= X"12341234";
avalon_master_readdatavalid <= '0';
avalon_master_waitreq <= '1';
-- Reset
rst_n <= '0';
wait for CLK_PERIOD * 2.5;
rst_n <= '1';
wait for CLK_PERIOD * 2;
-- Initiate CMD cycle
avalon_slave_address <= "0000";
wait until rising_edge(clk);
avalon_slave_writedata <= (27 downto 0 => '0') & "1000";
avalon_slave_write <= '1';
wait until rising_edge(clk);
avalon_slave_write <= '0';
wait for CLK_PERIOD * 20;
avalon_slave_address <= "0001";
wait until rising_edge(clk);
avalon_slave_writedata <= (27 downto 0 => '0') & "1111";
avalon_slave_write <= '1';
wait until rising_edge(clk);
avalon_slave_write <= '0';
wait for CLK_PERIOD * 20;
-- Loop refreshing
loop
wait for CLK_PERIOD * 50;
-- Initiate a refresh cycle
avalon_slave_address <= "0011";
wait until rising_edge(clk);
avalon_slave_write <= '1';
wait until rising_edge(clk);
avalon_slave_write <= '0';
-- Wait until bus grant
wait for CLK_PERIOD * 3;
avalon_master_waitreq <= '0';
wait for CLK_PERIOD;
-- Emulate that new read data is valid each cycle of the burst
avalon_master_readdatavalid <= '1';
for i in 0 to 15 loop
avalon_master_readdata <= std_logic_vector(to_unsigned(i*2 + ((i*2+1)*2**16), avalon_master_readdata'length));
wait for CLK_PERIOD;
end loop;
-- burst finished
avalon_master_readdatavalid <= '0';
loop
-- Wait until the previous 16 words have been shifted to LCD and new pixels
-- are requested
wait until avalon_master_read = '1' or irq = '1';
exit when irq = '1';
-- Wait some time for bus grant...
wait for CLK_PERIOD * 3;
-- Start providing some data
avalon_master_readdatavalid <= '1';
for i in 0 to 15 loop
avalon_master_readdata <= std_logic_vector(to_unsigned(i*2 + ((i*2+1)*2**16), avalon_master_readdata'length));
wait for CLK_PERIOD;
end loop;
avalon_master_readdatavalid <= '0';
end loop;
end loop;
end process;
end;

View 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;

View File

@ -0,0 +1,141 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity LCDDriver_tb is
end LCDDriver_tb;
architecture test of LCDDriver_tb is
constant CLK_PERIOD : time := 20 ns;
constant N_LED_MAX : integer := 255;
signal clk : std_logic := '0';
signal rst_n : std_logic := '1';
signal data_in : std_logic_vector(15 downto 0) := (others=> '0');
signal empty_in : std_logic := '1';
signal refresh_in : std_logic := '0';
signal cmd_en_in : std_logic := '0';
signal cmd_dcx_in : std_logic := '0';
signal cmd_data_in : std_logic_vector(7 downto 0) := (others => '0');
signal m_finished_in : std_logic := '0';
signal data_out : std_logic_vector(15 downto 0);
signal rd_n : std_logic;
signal wr_n : std_logic;
signal rs : std_logic;
signal cs_n : std_logic;
signal lcd_rdreq : std_logic;
signal rdreq_cnt : integer := 0;
signal busy : std_logic;
begin
-- Instantiate DUT
dut : entity work.LCDDriver
generic map (
F_CLK => 50000000
)
port map(
clk => clk,
rst_n => rst_n,
data_in => data_in,
empty_in => empty_in,
refresh_in => refresh_in,
cmd_en_in => cmd_en_in,
cmd_dcx_in => cmd_dcx_in,
cmd_data_in => cmd_data_in,
m_finished_in => m_finished_in,
data_out => data_out,
rd_n => rd_n,
wr_n => wr_n,
rs => rs,
cs_n => cs_n,
lcd_rdreq => lcd_rdreq,
busy => busy
);
-- Clocking process
clk_generation : process
begin
clk <= not clk;
wait for CLK_PERIOD / 2;
end process;
process (lcd_rdreq) begin
if rising_edge(lcd_rdreq) then
if (rdreq_cnt = 0) then
data_in <= "1111111111111111";
elsif (rdreq_cnt = 1) then
data_in <= "1111000000001111";
elsif (rdreq_cnt = 2) then
data_in <= "1111111100000000";
elsif (rdreq_cnt = 3) then
data_in <= "0000000011111111";
else
data_in <= "0000000000000000";
end if;
rdreq_cnt <= rdreq_cnt + 1;
end if;
end process;
tb : process
procedure wait_ready is
begin
if busy = '1' then
wait until busy = '0';
end if;
end procedure wait_ready;
procedure finish is
begin
wait until falling_edge(clk);
wait_ready;
wait;
end procedure finish ;
begin
-- Reset
rst_n <= '0';
wait for CLK_PERIOD * 2.5;
rst_n <= '1';
wait for CLK_PERIOD * 2;
wait_ready;
-- Test CMD
cmd_en_in <= '1';
cmd_dcx_in <= '1';
cmd_data_in <= "11010011";
wait for CLK_PERIOD * 2.5;
cmd_en_in <= '0';
wait_ready;
-- Test REFRESH
refresh_in <= '1';
wait for CLK_PERIOD * 2.5;
refresh_in <= '0';
wait for CLK_PERIOD * 4;
empty_in <= '0';
wait until rdreq_cnt = 4;
empty_in <= '1';
--m_finished_in => m_finished_in,
wait_ready;
-- Test finished
finish;
end process;
end;

View File

@ -0,0 +1,157 @@
-- altera vhdl_input_version vhdl_2008
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity PixTrans is
generic (
MAX_H : natural;
MAX_W : natural
);
port (
clk : in std_logic;
rst_n : in std_logic;
lcd_req : in std_logic;
data : out std_logic_vector(15 downto 0);
empty : out std_logic;
fifo_req : out std_logic;
fifo_q : in std_logic_vector(31 downto 0);
fifo_empty : in std_logic;
-- Currently configured width/height of the buffer
w : in natural;
h : in natural
);
end PixTrans;
architecture behavioral of PixTrans is
subtype Pixel is std_logic_vector(15 downto 0);
-- Generic constants
constant BLANK : Pixel := "0000000000000000"; --(others => '0');
-- Type definitions
type PIXEL_SOURCE is (S_BLANK, S_FIFO, S_BUFFER);
-- Inferred registers
signal pixbuf_reg, pixbuf_next : Pixel;
signal pixbufvalid_reg, pixbufvalid_next : boolean;
signal pos_x_reg, pos_x_next : integer range 1 to MAX_W;
signal pos_y_reg, pos_y_next : integer range 1 to MAX_H;
signal pix_src_reg, pix_src_next : PIXEL_SOURCE;
signal finished_next, finished_reg : std_logic;
-- Convenience signals
signal inBlankArea_reg, inBlankArea_next : boolean;
signal lcd_req_delayed_reg : std_logic;
begin
-- Update cursor
process(all) begin
finished_next <= finished_reg;
pos_y_next <= pos_y_reg;
pos_x_next <= pos_x_reg;
if lcd_req_delayed_reg = '1' then
if pos_x_reg = MAX_W and pos_y_reg = MAX_H then
pos_x_next <= 1;
pos_y_next <= 1;
elsif pos_x_reg = MAX_W then
pos_x_next <= 1;
pos_y_next <= pos_y_reg + 1;
else
pos_x_next <= pos_x_reg + 1;
end if;
if pos_x_reg = MAX_W and pos_y_reg = MAX_H then
finished_next <= '1' and not finished_reg;
else
finished_next <= '0';
end if;
end if;
inBlankArea_next <= pos_y_next > h or pos_x_next > w;
end process;
-- Data process
process(all) begin
pix_src_next <= pix_src_reg;
pixbufvalid_next <= pixbufvalid_reg;
-- FIFO output signals
fifo_req <= '0';
if lcd_req_delayed_reg = '1' then
if inBlankArea_next then
pix_src_next <= S_BLANK;
elsif pixbufvalid_reg then
-- Has valid pixel in pixel buffer
pix_src_next <= S_BUFFER;
pixbufvalid_next <= false;
else
fifo_req <= '1';
-- fifo_req should be kept high until pixel is available
if fifo_empty = '0' then
-- Must request pixel from FIFO
pix_src_next <= S_FIFO;
pixbufvalid_next <= true;
end if;
end if;
end if;
end process;
-- Data request multiplexer (pixel source)
with pix_src_reg select data <=
BLANK when S_BLANK,
fifo_q(15 downto 0) when S_FIFO,
pixbuf_reg when S_BUFFER;
-- Fill pixel buffer with the upper half word of the input FIFO word when
-- reading from the fifo
pixbuf_next <= fifo_q(31 downto 16) when pix_src_reg = S_FIFO else pixbuf_reg;
-- LCD Controller empty signal
process(all) begin
if fifo_empty = '1' then
empty <= '1';
else
empty <= finished_reg;
end if;
end process;
-- Clocking process/register inferrence
process(clk) begin
if rising_edge(clk) then
if rst_n = '0' then
pos_x_reg <= 1;
pos_y_reg <= 1;
pixbuf_reg <= BLANK;
pixbufvalid_reg <= false;
pix_src_reg <= S_BLANK;
inBlankArea_reg <= false;
finished_reg <= '0';
lcd_req_delayed_reg <= '0';
else
pos_x_reg <= pos_x_next;
pos_y_reg <= pos_y_next;
pixbuf_reg <= pixbuf_next;
pixbufvalid_reg <= pixbufvalid_next;
pix_src_reg <= pix_src_next;
inBlankArea_reg <= inBlankArea_next;
finished_reg <= finished_next;
lcd_req_delayed_reg <= lcd_req;
end if;
end if;
end process;
end behavioral ; -- behavioral

View File

@ -0,0 +1,90 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity PixTrans_tb is
end PixTrans_tb;
architecture test of PixTrans_tb is
constant CLK_PERIOD : time := 20 ns;
constant N_LED_MAX : integer := 255;
constant MAX_H : natural := 4;
constant MAX_W : natural := 4;
constant ACTUAL_H : natural := 2;
constant ACTUAL_W : natural := 2;
signal clk : std_logic := '0';
signal rst_n : std_logic;
signal fifo_empty, lcd_req : std_logic;
signal fifo_q : std_logic_vector(31 downto 0);
signal w, h : natural;
begin
w <= ACTUAL_W;
h <= ACTUAL_H;
-- Instantiate DUT
dut : entity work.PixTrans
generic map (
MAX_H => MAX_H,
MAX_W => MAX_W
)
port map(
clk => clk,
rst_n => rst_n,
lcd_req => lcd_req,
fifo_q => fifo_q,
fifo_empty => fifo_empty,
w => w,
h => h
);
-- Clocking process
clk_generation : process
begin
clk <= not clk;
wait for CLK_PERIOD / 2;
end process;
-- Testbench
tb : process
procedure getPixel is
begin
wait until rising_edge(clk);
lcd_req <= '1';
wait for CLK_PERIOD;
wait until rising_edge(clk);
lcd_req <= '0';
wait for CLK_PERIOD*3;
end procedure getPixel;
begin
-- Just let the FIFO interface always provide data
fifo_q <= X"FFFF" & X"F0F0";
fifo_empty <= '0';
lcd_req <= '0';
-- Reset
rst_n <= '0';
wait for CLK_PERIOD * 2.5;
rst_n <= '1';
wait for CLK_PERIOD * 2;
-- Get some pixels
for i in 1 to MAX_H*MAX_W loop
report "hello";
getPixel;
end loop;
-- Test finished
wait;
end process;
end;