Created
November 9, 2011 13:54
-
-
Save anonymous/1351496 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
------------------------------------------------------------------------------- | |
-- 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