From 2ad23d96798b0af0042c67eafa7fbffcc5e1037a Mon Sep 17 00:00:00 2001 From: umarcor Date: Thu, 30 Apr 2020 07:03:00 +0200 Subject: [PATCH] use generic packages --- doc/vhpidirect/examples/arrays.rst | 21 +++-- .../arrays/matrices/framebuffer/caux_x11.c | 1 + .../arrays/matrices/framebuffer/pkg.vhd | 9 +- vhpidirect/arrays/matrices/framebuffer/tb.vhd | 17 ++-- .../matrices/framebuffer/virt_vga/screen.vhd | 25 ++++-- .../matrices/framebuffer/virt_vga/tb.vhd | 88 +++++++++---------- 6 files changed, 93 insertions(+), 68 deletions(-) diff --git a/doc/vhpidirect/examples/arrays.rst b/doc/vhpidirect/examples/arrays.rst index a8928038..c068aed2 100644 --- a/doc/vhpidirect/examples/arrays.rst +++ b/doc/vhpidirect/examples/arrays.rst @@ -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 `. -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) `_. In the same package, foreign function ``save_screenshot`` is defined. It accepts a pointer to an array of integers, along @@ -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 `. - 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 `). 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 `, + 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 `). 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 `): @@ -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. @@ -277,5 +279,6 @@ implementation: either PNG/GIF or X11, as explained above. .. TIP:: VHDL package :cosimtree:`vga_cfg_pkg ` 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. diff --git a/vhpidirect/arrays/matrices/framebuffer/caux_x11.c b/vhpidirect/arrays/matrices/framebuffer/caux_x11.c index 1e7f3cc9..c78e4d55 100644 --- a/vhpidirect/arrays/matrices/framebuffer/caux_x11.c +++ b/vhpidirect/arrays/matrices/framebuffer/caux_x11.c @@ -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; diff --git a/vhpidirect/arrays/matrices/framebuffer/pkg.vhd b/vhpidirect/arrays/matrices/framebuffer/pkg.vhd index d128691e..226e5a9e 100644 --- a/vhpidirect/arrays/matrices/framebuffer/pkg.vhd +++ b/vhpidirect/arrays/matrices/framebuffer/pkg.vhd @@ -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; diff --git a/vhpidirect/arrays/matrices/framebuffer/tb.vhd b/vhpidirect/arrays/matrices/framebuffer/tb.vhd index ec199232..503f7974 100644 --- a/vhpidirect/arrays/matrices/framebuffer/tb.vhd +++ b/vhpidirect/arrays/matrices/framebuffer/tb.vhd @@ -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); @@ -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; @@ -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; diff --git a/vhpidirect/arrays/matrices/framebuffer/virt_vga/screen.vhd b/vhpidirect/arrays/matrices/framebuffer/virt_vga/screen.vhd index f1da7d92..0092b713 100644 --- a/vhpidirect/arrays/matrices/framebuffer/virt_vga/screen.vhd +++ b/vhpidirect/arrays/matrices/framebuffer/virt_vga/screen.vhd @@ -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; @@ -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; @@ -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; diff --git a/vhpidirect/arrays/matrices/framebuffer/virt_vga/tb.vhd b/vhpidirect/arrays/matrices/framebuffer/virt_vga/tb.vhd index 0c227dff..70761e58 100644 --- a/vhpidirect/arrays/matrices/framebuffer/virt_vga/tb.vhd +++ b/vhpidirect/arrays/matrices/framebuffer/virt_vga/tb.vhd @@ -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'; @@ -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;