Skip to content

Commit

Permalink
use generic packages
Browse files Browse the repository at this point in the history
  • Loading branch information
umarcor committed Apr 30, 2020
1 parent cc7e02d commit 39eab35
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 68 deletions.
21 changes: 12 additions & 9 deletions doc/vhpidirect/examples/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ In image generation and processing applications, it can be tedious to debug the
logs. Saving data from RAMs and/or typical graphics standards to images or video allows to spot visual artifacts easily.

This example is based on :ref:`COSIM:VHPIDIRECT:Examples:arrays:intvector:vhdlsized` from :ref:`intvector <COSIM:VHPIDIRECT:Examples:arrays:intvector>`.
A 2D array of integers is allocated in a VHDL package and it is used as a frame buffer. Each integer represents a pixel:
the 24 least significant bits are used for R, G and B (8 bits each); while the 8 most significant are not used.
A 2D array of integers is allocated in a (generic) VHDL package and it is used as a frame buffer. Each integer represents a
pixel: the 24 least significant bits are used for R, G and B (8 bits each); while the 8 most significant are not used.
See `Wikipedia: Color_depth#True_color_(24-bit) <https://en.wikipedia.org/wiki/Color_depth#True_color_(24-bit)>`_.

In the same package, foreign function ``save_screenshot`` is defined. It accepts a pointer to an array of integers, along
Expand All @@ -235,10 +235,12 @@ implementations are shown:
window on the desktop. Then, when ``save_screenshot`` is called, the canvas is updated with the content of the frame buffer.

.. HINT::
The resolution of the screen (frame buffer) is hardcoded in :cosimtree:`pkg.vhd <vhpidirect/arrays/matrices/framebuffer/pkg.vhd>`.
At the same time, the size of the canvas (X11 window) is hardcoded in the testbenches and passed to C as arguments of ``sim_init``
(see :cosimtree:`caux.c <vhpidirect/arrays/matrices/framebuffer/caux.c>`). Hence, in order to use other resolutions, both sources
might need to be modified. Contributions to improve this mechanism are welcome!
The resolution of the screen (frame buffer) is defined in :cosimtree:`pkg.vhd <vhpidirect/arrays/matrices/framebuffer/pkg.vhd>`,
which is a generic package. Corresponding generics are defined in the top-level entity (testbench). Hence, it is possible to
modify the size of the screen through CLI args.
At the same time, the size of the canvas (X11 window) is defined in the testbench and passed to C as arguments of ``sim_init``
(see :cosimtree:`caux.c <vhpidirect/arrays/matrices/framebuffer/caux.c>`). By default, the size of the window matches the
size of the screen (frame buffer). However, this is not a requirement.

Moreover, two different architectures are provided for the testbench (:cosimtree:`tb.vhd <vhpidirect/arrays/matrices/framebuffer/tb.vhd>`):

Expand All @@ -247,7 +249,7 @@ Moreover, two different architectures are provided for the testbench (:cosimtree
right and to the bottom as frames advance).

* In architecture ``bars``, a single frame/image is generated. The content of the buffer is set through an ``std_logic_vector(2 downto 0)``
(RGB) signal. A helper function (``RGB_to_integer``) provided in the package is used to convert the 3 bit signal into
(RGB) signal. A helper function (``RGB_to_integer``, provided in the package) is used to convert the 3 bit signal into
RGB24. The generated static pattern is eight equally spaced vertical bars, each correponding to a value of the 3 bit
signal; from left to right: black, red, green, yellow, blue, magenta, cyan and white.

Expand Down Expand Up @@ -277,5 +279,6 @@ implementation: either PNG/GIF or X11, as explained above.
.. TIP::
VHDL package :cosimtree:`vga_cfg_pkg <vhpidirect/arrays/matrices/framebuffer/virt_vga/cfg_pkg.vhd>` contains a table
(described as an array of records) with parameter values (pulse, porch, pixel clock rate, polarity, etc.) for +60 VGA/VESA/SXGA/XGA
modes. This table is used in ``vga_pattern`` and ``vga_screen``, to provide generics to ``vga_syn_gen``. However, as
explained in the hint above, the size of the *virtual screen* is hardcoded.
modes. This table is used in ``vga_pattern`` and ``vga_screen``, to provide generics to ``vga_syn_gen``. At the same time,
``vga_screen`` allows to set the size of the X11 window through generics. By default, the size of the window matches the
resolution of the selected mode.
1 change: 1 addition & 0 deletions vhpidirect/arrays/matrices/framebuffer/caux_x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ static uint xres;
static uint yres;

void sim_init(uint32_t width, uint32_t height) {
printf("sim_init %d %d\n", width, height);
xres = width;
yres = height;

Expand Down
9 changes: 6 additions & 3 deletions vhpidirect/arrays/matrices/framebuffer/pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ library ieee;
context ieee.ieee_std_context;

package pkg is
-- TODO: use a generic package, to set the width and height through top-level generics (CLI)
generic (
G_WIDTH : natural := 640;
G_HEIGHT : natural := 480
);

type screen_t is
array ( natural range 0 to 480-1, --768
natural range 0 to 640-1 ) of integer; --1368
array ( natural range 0 to G_HEIGHT-1,
natural range 0 to G_WIDTH-1 ) of integer;

shared variable screen: screen_t;

Expand Down
17 changes: 12 additions & 5 deletions vhpidirect/arrays/matrices/framebuffer/tb.vhd
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use work.pkg.all;

entity tb is
generic (
WIDTH : natural := 640;
HEIGHT : natural := 480
);
package tb_pkg is new work.pkg
generic map (
G_WIDTH => WIDTH,
G_HEIGHT => HEIGHT
);
use tb_pkg.all;
end tb;


architecture test of tb is
constant c_width : integer := screen'length(2);
constant c_height : integer := screen'length(1);
Expand All @@ -12,7 +19,7 @@ begin
variable h, i, j, d_x, d_y: integer;
constant w : natural := 100;
begin
sim_init(800, 600); -- X11 window size
sim_init(WIDTH, HEIGHT); -- X11 window size
report "screen size: " & to_string(c_width) & "x" & to_string(c_height) severity note;
report "pattern: test" severity note;

Expand Down Expand Up @@ -56,7 +63,7 @@ begin
process
variable color: std_logic_vector(2 downto 0) := (others=>'0');
begin
sim_init(800, 600); -- X11 window size
sim_init(WIDTH, HEIGHT); -- X11 window size
report "screen size: " & to_string(c_width) & "x" & to_string(c_height) severity note;
report "pattern: bars" severity note;

Expand Down
25 changes: 18 additions & 7 deletions vhpidirect/arrays/matrices/framebuffer/virt_vga/screen.vhd
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
library ieee;
context ieee.ieee_std_context;

use work.pkg.all;
use work.vga_cfg_pkg.all;

entity vga_screen is
generic (
G_SCREEN: natural
G_SCREEN : natural;
G_WWIDTH : natural := 0; -- X11 window width
G_WHEIGHT : natural := 0 -- X11 window height
);
port (
RST: in std_logic;
Expand All @@ -15,15 +16,20 @@ entity vga_screen is
RGB: in std_logic_vector(2 downto 0);
VID: in std_logic
);
constant cfg: VGA_config := VGA_configs(G_SCREEN);
package tb_pkg is new work.pkg
generic map (
G_WIDTH => cfg.width,
G_HEIGHT => cfg.height
);
use tb_pkg.all;
end entity;

architecture arch of vga_screen is
constant cfg: VGA_config := VGA_configs(G_SCREEN);
constant clk_period : time := (1.0/real(cfg.clk)) * 1 ms;

signal clk: std_logic := '0';
constant clk_period : time := (1.0/real(cfg.clk)) * 1 ms;

signal p_rst, p_hs, p_vs: std_logic;
signal clk, p_rst, p_hs, p_vs: std_logic := '0';

signal x: integer range -1 to cfg.width;
signal y: integer range -1 to cfg.height;
Expand All @@ -32,7 +38,12 @@ begin

proc_init: process
begin
sim_init(800, 600); -- X11 window size
-- X11 window size
if G_WWIDTH /= 0 and G_WHEIGHT /= 0 then
sim_init(G_WWIDTH, G_WHEIGHT);
else
sim_init(cfg.width, cfg.height);
end if;
wait;
end process;

Expand Down
88 changes: 44 additions & 44 deletions vhpidirect/arrays/matrices/framebuffer/virt_vga/tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use std.env.stop;
library ieee;
context ieee.ieee_std_context;

use work.pkg.all;

entity tb_vga is
generic (
G_SCREEN : natural := 4
);
end entity;

architecture arch of tb_vga is

constant c_screen : natural := 4;
constant clk_period : time := 20 ns;
signal clk, rst, save_video: std_logic := '0';

Expand All @@ -25,51 +25,51 @@ architecture arch of tb_vga is

begin

proc_clk: process
begin
clk <= '0'; wait for clk_period/2;
clk <= '1'; wait for clk_period/2;
end process;
proc_clk: process
begin
clk <= '0'; wait for clk_period/2;
clk <= '1'; wait for clk_period/2;
end process;

proc_main: process
begin
report "start simulation" severity note;
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for 35 ms;
report "end simulation" severity note;
save_video <= '1';
wait for 200 ns;
stop(0);
wait;
end process;
proc_main: process
begin
report "start simulation" severity note;
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for 35 ms;
report "end simulation" severity note;
save_video <= '1';
wait for 200 ns;
stop(0);
wait;
end process;


VIRT_VGA: entity work.vga_screen
generic map (
G_SCREEN => c_screen
)
port map (
RST => rst,
HSYNC => vga.hsync,
VSYNC => vga.vsync,
RGB => vga.rgb,
VID => save_video
);
VIRT_VGA: entity work.vga_screen
generic map (
G_SCREEN => G_SCREEN
)
port map (
RST => rst,
HSYNC => vga.hsync,
VSYNC => vga.vsync,
RGB => vga.rgb,
VID => save_video
);


UUT: entity work.vga_pattern
generic map (
G_SCREEN => c_screen
)
port map (
CLK => clk,
EN => '1',
RST => rst,
HSYNC => vga.hsync,
VSYNC => vga.vsync,
RGB => vga.rgb
);
UUT: entity work.vga_pattern
generic map (
G_SCREEN => G_SCREEN
)
port map (
CLK => clk,
EN => '1',
RST => rst,
HSYNC => vga.hsync,
VSYNC => vga.vsync,
RGB => vga.rgb
);

end architecture;

0 comments on commit 39eab35

Please sign in to comment.