Commit 09e4ee23 authored by goekce's avatar goekce
Browse files


# A basic graphics processor
The processor only knows how to render a list of sprites which have a velocity.
## Problems encountered
- GHDL does not support external signals ( Workaround:
- [using global signals](
## Potential questions
- In a testbench you want to wait for a signal to be activated in a non-sensitivized process with `wait for` statements. What could be the problem with the following?
wait for tlast = '1';
You have to add `wait on tlast for tlast = '1'`
<!--TODO I have to verify this in another simulator -->
- what happens if we do this after directly after reset:
for line in frame'range loop
for pixel in line'range loop
pixel <= '0';
end loop;
end loop;
## Handy resources
ENTITY ?= tb
default: wave.gtkw wave.ghw
tb.o: top.o
GHDL_OPTS = --std=08
GHDL = ghdl $(GHDL_OPTS)
.PRECIOUS: wave.ghw
wave.ghw: $(ENTITY)
@# ignore error in case we interrupt the sim using CTRL+C
-ghdl run $(GHDL_OPTS) $< --wave=$@
.PHONY: gtkwave
gtkwave: wave.gtkw
gtkwave $<
# creates a basic gtkwave savefile which loads the ghdl wave file
$(file >$@,[dumpfile] "$<")
%.o: %.vhd
ghdl analyze $(GHDL_OPTS) $<
%: %.o
ghdl elaborate $(GHDL_OPTS) $(@)
.PHONY: clean
$(RM) *.o *.cf
$(RM) wave.ghw
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
entity tb is
end entity;
architecture a of tb is
constant CLK_PERIOD : time := 10 ns;
constant LINE_PIXEL_COUNT: natural := 8;
constant LINE_COUNT: natural := 6;
signal clk: std_ulogic := '1';
signal rst: std_ulogic;
signal tlast: std_ulogic;
clk <= not clk after CLK_PERIOD;
duv: entity
port map(clk, rst, tlast);
wait for 100 ns;
rst <= '1';
wait for 100 ns;
rst <= '0';
report "Waiting for tlast";
wait on tlast until tlast = '1';
report "tlast active";
end process;
timeout: process
wait for 200 us;
report "Timeout" severity error;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity top is
generic (
LINE_PIXEL_COUNT: positive := 640;
LINE_COUNT: positive := 480;
MAX_SPRITE_COUNT: positive := 8
port (
clk, rst: std_ulogic;
--TODO axi output
tlast: out std_ulogic
architecture a of top is
constant MAX_VEL_X: natural := 3;
constant MAX_VEL_Y: natural := 3;
type line_t is array (0 to LINE_PIXEL_COUNT-1) of std_ulogic;
type frame_t is array (0 to LINE_COUNT-1) of line_t;
signal frame: frame_t;
type state_t is (init, run);
signal st: state_t;
subtype pixel_x_t is natural range 0 to LINE_PIXEL_COUNT-1;
subtype pixel_y_t is natural range 0 to LINE_COUNT-1;
signal line_pixel_ptr: pixel_x_t;
signal line_ptr: pixel_y_t;
type pos_vec_t is record
x: pixel_x_t;
y: pixel_y_t;
end record;
constant POS_VEC_ZERO: pos_vec_t := (0, 0);
type vel_vec_t is record
x: natural range 0 to MAX_VEL_X;
y: natural range 0 to MAX_VEL_Y;
end record;
constant VEL_VEC_ZERO: vel_vec_t := (0, 0);
type sprite_t is record
en: boolean;
pos: pos_vec_t;
vel: vel_vec_t;
end record;
constant SPRITE_INIT: sprite_t := (false, POS_VEC_ZERO, VEL_VEC_ZERO);
type sprites_t is array(0 to MAX_SPRITE_COUNT-1) of sprite_t;
constant SPRITES_INIT: sprites_t := (sprites_t'range => SPRITE_INIT);
signal sprites: sprites_t;
process (clk) is
if rising_edge(clk) then
if rst then
st <= state_t'left;
line_ptr <= 0;
line_pixel_ptr <= 0;
tlast <= '0';
sprites <= SPRITES_INIT;
end if;
-- state transition logic
case st is
when init =>
frame(line_ptr)(line_pixel_ptr) <= '1';
if line_pixel_ptr = line_pixel_ptr'subtype'right then
line_pixel_ptr <= 0;
if line_ptr = line_ptr'subtype'right then
line_ptr <= 0;
tlast <= '1';
st <= run;
line_ptr <= line_ptr + 1;
end if;
line_pixel_ptr <= line_pixel_ptr + 1;
end if;
when run =>
-- TODO update sprites
end case;
end if;
end process;
[dumpfile] "wave.ghw"
#{frame[0]} top.tb.duv.frame[0][0] top.tb.duv.frame[0][1] top.tb.duv.frame[0][2] top.tb.duv.frame[0][7]
#{frame[1]} top.tb.duv.frame[1][0] top.tb.duv.frame[1][1] top.tb.duv.frame[1][2] top.tb.duv.frame[1][7]
#{frame[4]} top.tb.duv.frame[4][0] top.tb.duv.frame[4][1] top.tb.duv.frame[4][2] top.tb.duv.frame[4][7]
#{frame[5]} top.tb.duv.frame[5][0] top.tb.duv.frame[5][1] top.tb.duv.frame[5][2] top.tb.duv.frame[5][7]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment