From 9db2542815efe7017d6ddb1c260ed859b490eb28 Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 18:20:33 +0200 Subject: [PATCH 01/11] copied the test card source and stared to reverse engineer it because why would it be documented at all --- svosrc/svo_parallelMem.v | 175 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 svosrc/svo_parallelMem.v diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v new file mode 100644 index 0000000..31cadba --- /dev/null +++ b/svosrc/svo_parallelMem.v @@ -0,0 +1,175 @@ +/* + * SVO - Simple Video Out FPGA Core + * + * Copyright (C) 2014 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1ns / 1ps +`include "svo_defines.vh" + +module svo_tcard #( `SVO_DEFAULT_PARAMS ) ( + input clk, resetn, + + // output stream + // tuser[0] ... start of frame + output reg out_axis_tvalid, //color output valid + input out_axis_tready, //next stage waits for color + output reg [SVO_BITS_PER_PIXEL-1:0] out_axis_tdata, //color data + output reg [0:0] out_axis_tuser //timeing +); +`SVO_DECLS + +localparam HOFFSET = ((32 - (SVO_HOR_PIXELS % 32)) % 32) / 2; +localparam VOFFSET = ((32 - (SVO_VER_PIXELS % 32)) % 32) / 2; + +localparam HOR_CELLS = (SVO_HOR_PIXELS + 31) / 32; +localparam VER_CELLS = (SVO_VER_PIXELS + 31) / 32; + +localparam BAR_W = (HOR_CELLS - 8 - HOR_CELLS%2) / 2; + +localparam X1 = 2; +localparam X2 = 2 + BAR_W; +localparam X3 = HOR_CELLS - 4 - BAR_W; +localparam X4 = HOR_CELLS - 4; + +function integer best_y_params; + input integer n, which; + integer best_y_blk; + integer best_y_off; + integer best_y_gap; +begin + best_y_blk = 0; + best_y_gap = 0; + best_y_off = 0; + + if (SVO_VER_PIXELS == 480) begin + best_y_blk = 3; + best_y_gap = 1; + best_y_off = 1; + end + + if (SVO_VER_PIXELS == 600) begin + best_y_blk = 3; + best_y_gap = 2; + best_y_off = 2; + end + + if (SVO_VER_PIXELS == 768) begin + best_y_blk = 4; + best_y_gap = 3; + best_y_off = 2; + end + + if (SVO_VER_PIXELS == 1080) begin + best_y_blk = 6; + best_y_gap = 2; + best_y_off = 5; + end + + if (which == 1) best_y_params = best_y_blk; + if (which == 2) best_y_params = best_y_gap; + if (which == 3) best_y_params = best_y_off; +end +endfunction + +localparam Y_BLK = best_y_params(VER_CELLS, 1); +localparam Y_GAP = best_y_params(VER_CELLS, 2); +localparam Y_OFF = best_y_params(VER_CELLS, 3); + +localparam Y1 = 0*Y_BLK + 0*Y_GAP + Y_OFF; +localparam Y2 = 1*Y_BLK + 0*Y_GAP + Y_OFF; +localparam Y3 = 1*Y_BLK + 1*Y_GAP + Y_OFF; +localparam Y4 = 2*Y_BLK + 1*Y_GAP + Y_OFF; +localparam Y5 = 2*Y_BLK + 2*Y_GAP + Y_OFF; +localparam Y6 = 3*Y_BLK + 2*Y_GAP + Y_OFF; + +reg [`SVO_XYBITS-1:0] hcursor; +reg [`SVO_XYBITS-1:0] vcursor; + +reg [`SVO_XYBITS-6:0] x; +reg [`SVO_XYBITS-6:0] y; + +reg [4:0] xOffset, yOffset; + +reg [31:0] rng; +reg [SVO_BITS_PER_RED-1:0] r; +reg [SVO_BITS_PER_GREEN-1:0] g; +reg [SVO_BITS_PER_BLUE-1:0] b; + + +always @(posedge clk) begin + if (!resetn) begin + hcursor <= 0; + vcursor <= 0; + x <= 0; + y <= 0; + xOffset <= HOFFSET; + yOffset <= VOFFSET; + out_axis_tvalid <= 0; + out_axis_tdata <= 0; + out_axis_tuser <= 0; + end else + if (!out_axis_tvalid || out_axis_tready) begin + if (hcursor == 0) begin + rng = y ^ 123456789; + end + + if (!xOffset || hcursor == 0) begin + r = 16 * rng[0] + 16 * rng[1] + 31 * rng[2]; + g = 16 * rng[3] + 16 * rng[4] + 31 * rng[5]; + b = 16 * rng[6] + 16 * rng[7] + 31 * rng[8]; + + if ({r, g, b} == 0) begin + r = 32; + g = 32; + b = 32; + end + end + + if (&xOffset || &yOffset) begin + r = 0; + g = 0; + b = 0; + end +//x,y kodirnáta szerinte szin beálitás r,g,b reg-ben + + out_axis_tvalid <= 1; + out_axis_tdata <= {b, g, r}; + out_axis_tuser[0] <= !hcursor && !vcursor; + + if (hcursor == SVO_HOR_PIXELS-1) begin + hcursor <= 0; + x <= 0; + xOffset <= HOFFSET; + if (vcursor == SVO_VER_PIXELS-1) begin + vcursor <= 0; + y <= 0; + yOffset <= VOFFSET; + end else begin + vcursor <= vcursor + 1; + if (&yOffset) + y <= y + 1; + yOffset <= yOffset + 1; + end + end else begin + hcursor <= hcursor + 1; + if (&xOffset) + x <= x + 1; + xOffset <= xOffset + 1; + end + end +end +endmodule From 591954ef63bf71281489aae8261c5596358c6c4e Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 19:13:20 +0200 Subject: [PATCH 02/11] somthing like this --- svosrc/svo_parallelMem.v | 159 ++++++++------------------------------- svosrc/verilator.sh | 2 +- 2 files changed, 32 insertions(+), 129 deletions(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 31cadba..7e55f63 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -25,151 +25,54 @@ module svo_tcard #( `SVO_DEFAULT_PARAMS ) ( // output stream // tuser[0] ... start of frame - output reg out_axis_tvalid, //color output valid - input out_axis_tready, //next stage waits for color + output wire out_axis_tvalid, //color output valid + input wire out_axis_tready, //next stage waits for color output reg [SVO_BITS_PER_PIXEL-1:0] out_axis_tdata, //color data - output reg [0:0] out_axis_tuser //timeing -); -`SVO_DECLS - -localparam HOFFSET = ((32 - (SVO_HOR_PIXELS % 32)) % 32) / 2; -localparam VOFFSET = ((32 - (SVO_VER_PIXELS % 32)) % 32) / 2; - -localparam HOR_CELLS = (SVO_HOR_PIXELS + 31) / 32; -localparam VER_CELLS = (SVO_VER_PIXELS + 31) / 32; + output reg [0:0] out_axis_tuser, //timeing -localparam BAR_W = (HOR_CELLS - 8 - HOR_CELLS%2) / 2; -localparam X1 = 2; -localparam X2 = 2 + BAR_W; -localparam X3 = HOR_CELLS - 4 - BAR_W; -localparam X4 = HOR_CELLS - 4; +input wire in_axis_tvalid, //input color valid +output wire in_axis_tready, //need color -function integer best_y_params; - input integer n, which; - integer best_y_blk; - integer best_y_off; - integer best_y_gap; -begin - best_y_blk = 0; - best_y_gap = 0; - best_y_off = 0; +output reg [`SVO_XYBITS-1:0] hcursor, +output reg [`SVO_XYBITS-1:0] vcursor, - if (SVO_VER_PIXELS == 480) begin - best_y_blk = 3; - best_y_gap = 1; - best_y_off = 1; - end - - if (SVO_VER_PIXELS == 600) begin - best_y_blk = 3; - best_y_gap = 2; - best_y_off = 2; - end +input wire [SVO_BITS_PER_RED-1:0] r, +input wire [SVO_BITS_PER_GREEN-1:0] g, +input wire [SVO_BITS_PER_BLUE-1:0] b +); +`SVO_DECLS - if (SVO_VER_PIXELS == 768) begin - best_y_blk = 4; - best_y_gap = 3; - best_y_off = 2; - end - if (SVO_VER_PIXELS == 1080) begin - best_y_blk = 6; - best_y_gap = 2; - best_y_off = 5; - end +assign out_axis_tdata <= {b, g, r}; +assign out_axis_tvalid <= in_axis_tvalid; +assign in_axis_tready <= out_axis_tready; - if (which == 1) best_y_params = best_y_blk; - if (which == 2) best_y_params = best_y_gap; - if (which == 3) best_y_params = best_y_off; +initial begin + hcursor <= 0; + vcursor <= 0; + out_axis_tuser <= 0; end -endfunction - -localparam Y_BLK = best_y_params(VER_CELLS, 1); -localparam Y_GAP = best_y_params(VER_CELLS, 2); -localparam Y_OFF = best_y_params(VER_CELLS, 3); -localparam Y1 = 0*Y_BLK + 0*Y_GAP + Y_OFF; -localparam Y2 = 1*Y_BLK + 0*Y_GAP + Y_OFF; -localparam Y3 = 1*Y_BLK + 1*Y_GAP + Y_OFF; -localparam Y4 = 2*Y_BLK + 1*Y_GAP + Y_OFF; -localparam Y5 = 2*Y_BLK + 2*Y_GAP + Y_OFF; -localparam Y6 = 3*Y_BLK + 2*Y_GAP + Y_OFF; - -reg [`SVO_XYBITS-1:0] hcursor; -reg [`SVO_XYBITS-1:0] vcursor; - -reg [`SVO_XYBITS-6:0] x; -reg [`SVO_XYBITS-6:0] y; - -reg [4:0] xOffset, yOffset; - -reg [31:0] rng; -reg [SVO_BITS_PER_RED-1:0] r; -reg [SVO_BITS_PER_GREEN-1:0] g; -reg [SVO_BITS_PER_BLUE-1:0] b; - - -always @(posedge clk) begin +always @(posedge in_axis_tvalid or resetn) begin if (!resetn) begin hcursor <= 0; vcursor <= 0; - x <= 0; - y <= 0; - xOffset <= HOFFSET; - yOffset <= VOFFSET; - out_axis_tvalid <= 0; - out_axis_tdata <= 0; out_axis_tuser <= 0; - end else - if (!out_axis_tvalid || out_axis_tready) begin - if (hcursor == 0) begin - rng = y ^ 123456789; - end - - if (!xOffset || hcursor == 0) begin - r = 16 * rng[0] + 16 * rng[1] + 31 * rng[2]; - g = 16 * rng[3] + 16 * rng[4] + 31 * rng[5]; - b = 16 * rng[6] + 16 * rng[7] + 31 * rng[8]; + end else begin + out_axis_tuser[0] <= (hcursor==0) && (vcursor==0); - if ({r, g, b} == 0) begin - r = 32; - g = 32; - b = 32; - end - end - - if (&xOffset || &yOffset) begin - r = 0; - g = 0; - b = 0; - end -//x,y kodirnáta szerinte szin beálitás r,g,b reg-ben - - out_axis_tvalid <= 1; - out_axis_tdata <= {b, g, r}; - out_axis_tuser[0] <= !hcursor && !vcursor; - - if (hcursor == SVO_HOR_PIXELS-1) begin - hcursor <= 0; - x <= 0; - xOffset <= HOFFSET; - if (vcursor == SVO_VER_PIXELS-1) begin - vcursor <= 0; - y <= 0; - yOffset <= VOFFSET; - end else begin - vcursor <= vcursor + 1; - if (&yOffset) - y <= y + 1; - yOffset <= yOffset + 1; - end + if (hcursor == SVO_HOR_PIXELS-1) begin + hcursor <= 0; + if (vcursor == SVO_VER_PIXELS-1) begin + vcursor <= 0; end else begin - hcursor <= hcursor + 1; - if (&xOffset) - x <= x + 1; - xOffset <= xOffset + 1; + vcursor <= vcursor + 1; end + end else begin + hcursor <= hcursor + 1; end + end end + endmodule diff --git a/svosrc/verilator.sh b/svosrc/verilator.sh index e36d8aa..6ac69bc 100644 --- a/svosrc/verilator.sh +++ b/svosrc/verilator.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ex -verilator -exe --trace -Wno-fatal --cc verilator.v svo_tcard.v svo_pong.v svo_utils.v svo_enc.v verilator.cc +verilator -exe --trace -Wno-fatal --cc verilator.v svo_tcard.v svo_pong.v svo_utils.v svo_enc.v svo_parallelMem.v verilator.cc make -C obj_dir/ -f Vverilator.mk ./obj_dir/Vverilator | pv -l -w 60 > testbench.out python out2ppm.py testbench.out From c979147e8e95e79d6f49323d85ef8d348757345b Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 20:20:49 +0200 Subject: [PATCH 03/11] now it should build --- svosrc/svo_parallelMem.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 7e55f63..680f4e9 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -44,9 +44,9 @@ input wire [SVO_BITS_PER_BLUE-1:0] b `SVO_DECLS -assign out_axis_tdata <= {b, g, r}; -assign out_axis_tvalid <= in_axis_tvalid; -assign in_axis_tready <= out_axis_tready; +assign out_axis_tdata = {b, g, r}; +assign out_axis_tvalid = in_axis_tvalid; +assign in_axis_tready = out_axis_tready; initial begin hcursor <= 0; From 4438b16b48da0598a806d941468fd2ed67893f9f Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 20:24:51 +0200 Subject: [PATCH 04/11] this needs to be a wire --- svosrc/svo_parallelMem.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 680f4e9..403142d 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -27,7 +27,7 @@ module svo_tcard #( `SVO_DEFAULT_PARAMS ) ( // tuser[0] ... start of frame output wire out_axis_tvalid, //color output valid input wire out_axis_tready, //next stage waits for color - output reg [SVO_BITS_PER_PIXEL-1:0] out_axis_tdata, //color data + output wire [SVO_BITS_PER_PIXEL-1:0] out_axis_tdata, //color data output reg [0:0] out_axis_tuser, //timeing From 07044e1901ffe34f80af2bb894f952bd7cbcc692 Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 20:26:29 +0200 Subject: [PATCH 05/11] forgot to rename --- svosrc/svo_parallelMem.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 403142d..45085e2 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -20,7 +20,7 @@ `timescale 1ns / 1ps `include "svo_defines.vh" -module svo_tcard #( `SVO_DEFAULT_PARAMS ) ( +module svo_parallelMem #( `SVO_DEFAULT_PARAMS ) ( input clk, resetn, // output stream From 05b4adb2431e4c295319f216e532c7dfdfc7a410 Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Fri, 10 Apr 2026 20:27:45 +0200 Subject: [PATCH 06/11] forgot to set edge --- svosrc/svo_parallelMem.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 45085e2..51b8895 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -54,7 +54,7 @@ initial begin out_axis_tuser <= 0; end -always @(posedge in_axis_tvalid or resetn) begin +always @(posedge in_axis_tvalid or negedge resetn) begin if (!resetn) begin hcursor <= 0; vcursor <= 0; From 9acb9bf20f89b1707e72a9035ac61ffeca8d5a4b Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Sun, 12 Apr 2026 00:55:04 +0200 Subject: [PATCH 07/11] removed unused port --- svosrc/svo_parallelMem.v | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 51b8895..8c03d05 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -21,7 +21,7 @@ `include "svo_defines.vh" module svo_parallelMem #( `SVO_DEFAULT_PARAMS ) ( - input clk, resetn, + input resetn, // output stream // tuser[0] ... start of frame @@ -31,15 +31,15 @@ module svo_parallelMem #( `SVO_DEFAULT_PARAMS ) ( output reg [0:0] out_axis_tuser, //timeing -input wire in_axis_tvalid, //input color valid -output wire in_axis_tready, //need color + input wire in_axis_tvalid, //input color valid + output wire in_axis_tready, //need color + + output reg [`SVO_XYBITS-1:0] hcursor, + output reg [`SVO_XYBITS-1:0] vcursor, -output reg [`SVO_XYBITS-1:0] hcursor, -output reg [`SVO_XYBITS-1:0] vcursor, - -input wire [SVO_BITS_PER_RED-1:0] r, -input wire [SVO_BITS_PER_GREEN-1:0] g, -input wire [SVO_BITS_PER_BLUE-1:0] b + input wire [SVO_BITS_PER_RED-1:0] r, + input wire [SVO_BITS_PER_GREEN-1:0] g, + input wire [SVO_BITS_PER_BLUE-1:0] b ); `SVO_DECLS From ec5becd67bd13342841f9088eca4ccacbe124d90 Mon Sep 17 00:00:00 2001 From: Egy_ember Date: Tue, 14 Apr 2026 23:14:12 +0200 Subject: [PATCH 08/11] fiexed logic bug --- svosrc/svo_parallelMem.v | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 8c03d05..3abfc56 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -21,7 +21,7 @@ `include "svo_defines.vh" module svo_parallelMem #( `SVO_DEFAULT_PARAMS ) ( - input resetn, + input clk, resetn, // output stream // tuser[0] ... start of frame @@ -54,23 +54,24 @@ initial begin out_axis_tuser <= 0; end -always @(posedge in_axis_tvalid or negedge resetn) begin +always @(posedge clk or negedge resetn) begin if (!resetn) begin hcursor <= 0; vcursor <= 0; out_axis_tuser <= 0; end else begin out_axis_tuser[0] <= (hcursor==0) && (vcursor==0); - - if (hcursor == SVO_HOR_PIXELS-1) begin - hcursor <= 0; - if (vcursor == SVO_VER_PIXELS-1) begin - vcursor <= 0; + if (out_axis_tready) begin + if (hcursor == SVO_HOR_PIXELS-1) begin + hcursor <= 0; + if (vcursor == SVO_VER_PIXELS-1) begin + vcursor <= 0; + end else begin + vcursor <= vcursor + 1; + end end else begin - vcursor <= vcursor + 1; + hcursor <= hcursor + 1; end - end else begin - hcursor <= hcursor + 1; end end end From c46584494d232ba7ae7aab39e3241eb8846f5d78 Mon Sep 17 00:00:00 2001 From: Egyember <79502228+Egyember@users.noreply.github.com> Date: Tue, 14 Apr 2026 23:40:41 +0200 Subject: [PATCH 09/11] Update README --- README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README b/README index 3470bf3..88f8294 100644 --- a/README +++ b/README @@ -73,6 +73,11 @@ The following cores can be used to create video streams: A video DMA controller. Has a read-only AXI4 master interface to access the video memory. + svo_parallelMem.v + A simple interface for hooking up cosume stream generators. Outputs + the screen cordinates and asembles the rgb color data for the next + stage. + See also svo_utils.v for various helpers for combining video streams. The svo_pong core is in fact a collection of various cores generating video overlays that are combined using the helper modules from svo_utils.v. So From a8d61fcf7358bcda5a12e7a1ad6cdcb352d8670c Mon Sep 17 00:00:00 2001 From: Egyember <79502228+Egyember@users.noreply.github.com> Date: Tue, 14 Apr 2026 23:44:19 +0200 Subject: [PATCH 10/11] fixed typo --- README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index 88f8294..2bab635 100644 --- a/README +++ b/README @@ -74,9 +74,9 @@ The following cores can be used to create video streams: access the video memory. svo_parallelMem.v - A simple interface for hooking up cosume stream generators. Outputs - the screen cordinates and asembles the rgb color data for the next - stage. + A simple interface for hooking up costume stream generators. + Outputs the screen coordinates and assembles the rgb color + data for the next stage. See also svo_utils.v for various helpers for combining video streams. The svo_pong core is in fact a collection of various cores generating video From a81eae6697513a033c80bd65934996ff3a4e4971 Mon Sep 17 00:00:00 2001 From: Egyember <79502228+Egyember@users.noreply.github.com> Date: Fri, 17 Apr 2026 14:24:20 +0200 Subject: [PATCH 11/11] updated copyright svo_parallelMem.v --- svosrc/svo_parallelMem.v | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/svosrc/svo_parallelMem.v b/svosrc/svo_parallelMem.v index 3abfc56..8e4bc8c 100644 --- a/svosrc/svo_parallelMem.v +++ b/svosrc/svo_parallelMem.v @@ -1,8 +1,7 @@ /* * SVO - Simple Video Out FPGA Core * - * Copyright (C) 2014 Clifford Wolf - * + * Copyright (C) 2026 Gyenge Zsombor * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies.