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

initial

parents
# 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 (https://github.com/ghdl/ghdl/issues/24). Workaround:
- [using global signals](https://stackoverflow.com/questions/40286725/how-can-i-get-internal-signals-to-testbench-in-vhdl-97-and-isim/40313051#40313051)
## 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?
```vhdl
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
- https://www.synthworks.com/downloads/type_pkg_quickref.pdf
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
wave.gtkw:
$(file >$@,[dumpfile] "$<")
%.o: %.vhd
ghdl analyze $(GHDL_OPTS) $<
%: %.o
ghdl elaborate $(GHDL_OPTS) $(@)
.PHONY: clean
clean:
$(RM) *.o *.cf
$(RM) $(ENTITY)
$(RM) wave.ghw
ghdl.mk
\ 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;
begin
clk <= not clk after CLK_PERIOD;
duv: entity work.top
generic map(LINE_PIXEL_COUNT, LINE_COUNT)
port map(clk, rst, tlast);
process
begin
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";
std.env.finish;
end process;
timeout: process
begin
wait for 200 us;
report "Timeout" severity error;
std.env.finish;
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
);
end;
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;
begin
process (clk) is
begin
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;
else
line_ptr <= line_ptr + 1;
end if;
else
line_pixel_ptr <= line_pixel_ptr + 1;
end if;
when run =>
-- TODO update sprites
end case;
end if;
end process;
end;
[dumpfile] "wave.ghw"
top.tb.clk
top.tb.rst
top.tb.tlast
-
top.tb.duv.st
top.tb.duv.line_pixel_ptr
top.tb.duv.line_ptr
-
@28
#{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