Skip to content

Instantly share code, notes, and snippets.

Created November 9, 2011 13:54
Show Gist options
  • Save anonymous/1351496 to your computer and use it in GitHub Desktop.
Save anonymous/1351496 to your computer and use it in GitHub Desktop.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity lcd_master is
port (
clk : in std_logic;
reset_n : in std_logic;
-- avalon signals
avalon_read : out std_logic;
avalon_address : out std_logic_vector(31 downto 0);
avalon_waitrequest : in std_logic;
avalon_readdata : in std_logic_vector(7 downto 0);
avalon_readdatavalid : in std_logic;
avalon_burstcount : out std_logic_vector(7 downto 0); -- make configurable
-- timing singal
frame_start : in std_logic;
-- config data
frame_address : in std_logic_vector(31 downto 0);
frame_length : in std_logic_vector(31 downto 0);
-- fifo signals
fifo_level : in std_logic_vector(7 downto 0); -- make configurable
fifo_data : out std_logic_vector(7 downto 0);
fifo_write : out std_logic
);
end lcd_master;
architecture rtl of lcd_master is
type fsm_t is (st_idle, st_setup_read, st_read);
signal cur_address, new_address, next_address : std_logic_vector(31 downto 0);
signal remaining_bytes, new_remaining_bytes, next_remaining_bytes : std_logic_vector(31 downto 0);
signal cur_burstcount, next_burstcount : std_logic_vector(7 downto 0);
signal cur_state : fsm_t;
signal next_state : fsm_t;
begin
frame:
process (clk, reset_n, new_address, new_remaining_bytes)
begin
if (reset_n = '0') then
cur_address <= (others => '0');
remaining_bytes <= (others => '0');
elsif (rising_edge(clk)) then
cur_address <= new_address;
remaining_bytes <= new_remaining_bytes;
end if;
end process;
with frame_start select
new_address <=
frame_address when '1',
next_address when others;
with frame_start select
new_remaining_bytes <=
frame_length when '1',
next_remaining_bytes when others;
seq:
process (clk, reset_n, next_state)
begin
if (reset_n = '0') then
cur_state <= st_idle;
cur_burstcount <= (others => '0');
elsif (rising_edge(clk)) then
cur_state <= next_state;
cur_burstcount <= next_burstcount;
end if;
end process;
com:
process (cur_state, fifo_level, remaining_bytes, avalon_waitrequest, avalon_readdatavalid, cur_address, cur_burstcount)
variable max_burst_size : std_logic_vector(7 downto 0);
begin
avalon_address <= cur_address;
avalon_read <= '0';
avalon_burstcount <= cur_burstcount;
fifo_write <= '0';
next_address <= cur_address;
next_remaining_bytes <= remaining_bytes;
next_burstcount <= cur_burstcount;
next_state <= st_idle;
case cur_state is
when st_idle =>
if (fifo_level(7) = '0' and remaining_bytes /= 0) then
next_state <= st_setup_read;
avalon_address <= cur_address;
avalon_read <= '1';
max_burst_size := not fifo_level;
if max_burst_size + 1 /= 0 then
max_burst_size := max_burst_size + 1;
end if;
if (max_burst_size > remaining_bytes) then
max_burst_size := remaining_bytes(7 downto 0);
end if;
avalon_burstcount <= max_burst_size;
next_burstcount <= max_burst_size;
else
next_state <= st_idle;
end if;
when st_setup_read =>
if (avalon_waitrequest = '1') then
-- waiting, keep signal on bus
avalon_address <= cur_address;
avalon_read <= '1';
avalon_burstcount <= cur_burstcount;
next_burstcount <= cur_burstcount;
next_state <= st_setup_read;
else
-- setup finished
next_state <= st_read;
next_address <= cur_address + cur_burstcount;
next_remaining_bytes <= remaining_bytes - cur_burstcount;
end if;
when st_read =>
if (avalon_readdatavalid = '1') then
fifo_write <= '1';
next_burstcount <= cur_burstcount - 1;
-- run until the burst is done
if (cur_burstcount /= 1) then
next_state <= st_read;
else
next_state <= st_idle;
end if;
else
next_state <= st_read;
end if;
end case;
end process;
data:
fifo_data <= avalon_readdata;
end rtl;
-------------------------------------------------------------------------------
-- Title : Testbench for design "lcd_master"
-- Project :
-------------------------------------------------------------------------------
-- File : lcd_master_tb.vhd
-- Author : Simon Schubert <corecode@herb>
-- Company :
-- Created : 2011-11-08
-- Last update: 2011-11-09
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- Copyright (c) 2011
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-11-08 1.0 corecode Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-------------------------------------------------------------------------------
entity lcd_master_tb is
end lcd_master_tb;
-------------------------------------------------------------------------------
architecture test of lcd_master_tb is
component lcd_master
port (
clk : in std_logic;
reset_n : in std_logic;
avalon_read : out std_logic;
avalon_address : out std_logic_vector(31 downto 0);
avalon_waitrequest : in std_logic;
avalon_readdata : in std_logic_vector(7 downto 0);
avalon_readdatavalid : in std_logic;
avalon_burstcount : out std_logic_vector(7 downto 0);
frame_start : in std_logic;
frame_address : in std_logic_vector(31 downto 0);
frame_length : in std_logic_vector(31 downto 0);
fifo_level : in std_logic_vector(7 downto 0);
fifo_data : out std_logic_vector(7 downto 0);
fifo_write : out std_logic);
end component;
-- component ports
signal clk : std_logic := '0';
signal reset_n : std_logic;
signal avalon_read : std_logic;
signal avalon_address : std_logic_vector(31 downto 0);
signal avalon_waitrequest : std_logic;
signal avalon_readdata : std_logic_vector(7 downto 0);
signal avalon_readdatavalid : std_logic;
signal avalon_burstcount : std_logic_vector(7 downto 0);
signal frame_start : std_logic;
signal frame_address : std_logic_vector(31 downto 0);
signal frame_length : std_logic_vector(31 downto 0);
signal fifo_level : std_logic_vector(7 downto 0) := (others => '0');
signal fifo_data : std_logic_vector(7 downto 0);
signal fifo_write : std_logic;
type avalon_bus_state_t is (st_idle, st_setup, st_burst);
signal avalon_bus_state : avalon_bus_state_t := st_idle;
signal avalon_bus_burstcount : unsigned(7 downto 0);
signal fifo_drain_cycle : integer := 0;
begin -- test
-- component instantiation
DUT: lcd_master
port map (
clk => clk,
reset_n => reset_n,
avalon_read => avalon_read,
avalon_address => avalon_address,
avalon_waitrequest => avalon_waitrequest,
avalon_readdata => avalon_readdata,
avalon_readdatavalid => avalon_readdatavalid,
avalon_burstcount => avalon_burstcount,
frame_start => frame_start,
frame_address => frame_address,
frame_length => frame_length,
fifo_level => fifo_level,
fifo_data => fifo_data,
fifo_write => fifo_write);
-- clock generation
clk <= not clk after 10 ns;
-- constants
frame_address <= x"000b8000";
frame_length <= x"0000000a";
rst: process
begin
reset_n <= '0';
wait for 10 ns;
reset_n <= '1';
wait;
end process;
frame_sync: process
begin
frame_start <= '1';
wait for 20 ns;
frame_start <= '1';
wait until clk = '1';
wait until clk = '0';
frame_start <= '0';
wait for 500 ns;
frame_start <= '1';
wait until clk = '1';
wait until clk = '0';
frame_start <= '0';
wait;
end process;
fifo: process(clk)
variable new_level : integer;
begin
if rising_edge(clk) then
new_level := to_integer(unsigned(fifo_level));
if fifo_write = '1' then
new_level := new_level + 1;
end if;
if fifo_drain_cycle = 9 then
fifo_drain_cycle <= 0;
if new_level > 3 then
new_level := new_level - 3;
else
new_level := 0;
end if;
else
fifo_drain_cycle <= fifo_drain_cycle + 1;
end if;
fifo_level <= std_logic_vector(to_unsigned(new_level, 8));
end if;
end process;
avalon_slave: process(clk, avalon_bus_state, avalon_readdatavalid, avalon_bus_burstcount)
variable burstcount : std_logic_vector(7 downto 0);
begin
if rising_edge(clk) then
avalon_readdata <= "UUUUUUUU";
case avalon_bus_state is
when st_idle =>
if avalon_read = '1' then
avalon_waitrequest <= '1';
avalon_bus_burstcount <= unsigned(avalon_burstcount);
avalon_bus_state <= st_setup;
end if;
when st_setup =>
avalon_waitrequest <= '0';
avalon_bus_state <= st_burst;
when st_burst =>
if avalon_readdatavalid = '1' then
avalon_bus_burstcount <= avalon_bus_burstcount - 1;
end if;
if avalon_bus_burstcount = 1 then
avalon_bus_state <= st_idle;
else
-- add some wait states
if avalon_bus_burstcount mod 3 = 0 then
avalon_readdatavalid <= '0';
else
avalon_readdata <= std_logic_vector(avalon_bus_burstcount);
avalon_readdatavalid <= '1';
end if;
end if;
end case;
end if;
end process;
end test;
-------------------------------------------------------------------------------
configuration lcd_master_tb_test_cfg of lcd_master_tb is
for test
end for;
end lcd_master_tb_test_cfg;
-------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment