inserting text into a video stream (from a pre-existing video source)

I would like to superimpose some text into a video stream coming from a camera into my fpga. Lets say I would like to print the values of several registers to the screen as simple ascii text. This text would be superimposed over the incoming video stream. Does anyone know if there exists a core, or some free vhdl floating around somewhere to do this kind of thing? I have seen some cores that do VGA timing generation, then insert pixel values values from a look up table (but these dont do text from what I can tell, and must be controlled by a microprocessor).

The problem with these is that they dont really do what I want. Really what I want is a function that would convert the value of a register into say, hex or base 10 ascii text, and then count the number of rows/columns of video coming in, and insert black or white pixels into the video stream as appropriate to make those characters appear (superimposed) on the output video stream.

Anyone have any ideas or thoughts?

thanks.

Reply to
wallge
Loading thread data ...

There is a project called display test on

formatting link

originally this did exactly what you wanted using a block ram initialised with ascii bitmaps and a second ram holding the text to be displayed. It had a bus which could be attached to a state machine or microprocessor. I used it to display 16 32 bit registers on the screen.

have a look, I can't remember how much code I left in. If you don't find anything else ping me and I'll try and did up the original. Away in China for the next 2 weeks however ...

/MikeJ

Reply to
MikeJ

What format is your incoming video in?

Assuming it's got something like an LVALID and FVALID (and DVALID if the clk is not the same as the pixel clock), I would use a BRAM as a character frame buffer, decode the registers and stick the cahracters into that. Then another BRAM can have an array of bits indexed by character (make them 8x8 for ease :-) that can be used by a process which keeps track of the location of the pixel and which of the character locations you are in.

You could have a small state machine run at the end of each frame to update the character frame buffer with the values you want for next time around during the vblank. Or double buffer.

Or do you really want to have something which looks like ENTITY reg_to_screen ( clk reset registervalue (31 downto 0) xloc, yloc

vsync, hsync video_out);

which you can then instantiate a number of times and then combine the video_out signals together? If so, you'll end up duplicating the character->pixels map unnecesarily.

There's some thoughts for you :-)

Cheers, Martin

--
martin.j.thompson@trw.com 
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.net/electronics.html
Reply to
Martin Thompson

Yeah. I might be able to help although I don't know what you are using. Xilinx? Spartans? Virtex? VHDL? Verilog?

Can we assume that you already have a VGA display that is outputting? And so can we assume that you have row and column registers in your design?

Brad Smallridge AiVision dot com

Reply to
Brad Smallridge

Reply to
wallge

You might get some hints by looking at the data sheet for the STV5730A OSD chip.

Best regards, Spehro Pefhany

--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
Reply to
Spehro Pefhany

Well this is Xilinx specific but take a look at the three modules below: overlay,vga_dump_ram

What I remember is that the row and column registers point to both the dump RAM and the font ROM at the same time. With the lower bits going to the font ROM. Your idea of using

8 by 8 fonts is a good one, even if you don't use all the rows or columns of the font.

These modules create a one bit output that must be anded into your video stream.

Sorry I wrote these before I was inferring RAMs and ROMs but I think the Altera switch should be straight forward.

You also mentioned that you want to spit out the values of a register which will take some doing because you will need to mux the nibbles somehow.

Good Luck,

Brad Smallridge AiVision

library IEEE; use IEEE.STD_LOGIC_1164.ALL;

entity overlay is port( vga_clk : in std_logic; vga_reset : in std_logic; vga_row : in std_logic_vector( 8 downto 0); vga_col : in std_logic_vector(11 downto 0); q : out std_logic; wr_clk : in std_logic; wr_reset : in std_logic; wr_en : in std_logic; wr_stop : in std_logic; wr_addr : in std_logic_vector(11 downto 0); wr_data : in std_logic_vector( 7 downto 0) ); end overlay;

architecture behave of overlay is

component vga_dump_ram is port ( rst : in std_logic; clk_a : in std_logic; wr_a : in std_logic; data_a : in std_logic_vector(7 downto 0); addr_a : in std_logic_vector(11 downto 0); clk_b : in std_logic; addr_b : in std_logic_vector(11 downto 0); high_b : in std_logic; -- high nibble dout_b : out std_logic_vector(3 downto 0) ); end component;

signal vga_nibble_addr : std_logic_vector(11 downto 0); signal vga_nibble_high : std_logic; signal vga_nibble : std_logic_vector( 3 downto 0);

component vga_font is port ( clk : in std_logic; rst : in std_logic; addr : in std_logic_vector(14 downto 0); q : out std_logic ); end component;

signal vga_font_addr : std_logic_vector(14 downto 0); signal vga_font_row_1 : std_logic_vector( 2 downto 0); signal vga_font_row_2 : std_logic_vector( 2 downto 0); signal vga_font_col_1 : std_logic_vector( 2 downto 0); signal vga_font_col_2 : std_logic_vector( 2 downto 0); signal vga_font_bit : std_logic; signal vga_font_bit_1 : std_logic; signal vga_font_bit_2 : std_logic; signal vga_font_bit_3 : std_logic; signal vga_font_bit_4 : std_logic;

-- added for wr_stop timing signal wr_data_1 : std_logic_vector( 7 downto 0); signal wr_data_2 : std_logic_vector( 7 downto 0); signal wr_addr_1 : std_logic_vector(11 downto 0); signal wr_addr_2 : std_logic_vector(11 downto 0); signal wr_en_1 : std_logic; signal wr_en_2 : std_logic;

begin

-- This process adds two clock delays to the -- address font look-up-table and compensates -- for the character nibble look-up-table delay vga_font_addr_process: process(vga_clk) begin if(vga_clk'event and vga_clk='1') then vga_font_row_1 "READ_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE WRITE_WIDTH_A => 9, -- Valid values are 1,2,4,9,18 or 36 WRITE_WIDTH_B => 9) -- Valid values are 1,2,4,9,18 or 36

port map ( CASCADEOUTA => open, -- 1-bit cascade output CASCADEOUTB => open, -- 1-bit cascade output DOA => open, -- 32-bit A port Data Output DOB => dob, -- 32-bit B port Data Output DOPA => open, -- 4-bit A port Parity Output DOPB => open, -- 4-bit B port Parity Output ADDRA => addra, -- 15-bit A port Address Input ADDRB => addrb, -- 15-bit B port Address Input CASCADEINA => '0', -- 1-bit cascade A input CASCADEINB => '0', -- 1-bit cascade B input CLKA => clk_a, -- Port A Clock CLKB => clk_b, -- Port B Clock DIA => dia, -- 32-bit A port Data Input DIB => (others=>'1'), -- 32-bit B port Data Input DIPA => (others=>'1'), -- 4-bit A port parity Input DIPB => (others=>'1'), -- 4-bit B port parity Input ENA => '1', -- 1-bit A port Enable Input ENB => '1', -- 1-bit B port Enable Input REGCEA => '1', -- 1-bit A port register enable input REGCEB => '1', -- 1-bit B port register enable input SSRA => '0', -- 1-bit A port Synchronous Set/Reset Input SSRB => '0', -- 1-bit B port Synchronous Set/Reset Input WEA => wea, -- 4-bit A port Write Enable Input WEB => (others=>'0') ); -- 4-bit B port Write Enable Input

dout_b

Reply to
Brad Smallridge

You wont be able to be video-format-agnostic for a number of reasons :

To properly CHAR insert you need to phase-lock to the incomming Line Sync (often called GenLock) - if you do not do this, the chars jitter about as you have two clock domains.

You also need to Sync to Frame, and count lines, to decide when to start the CHAR insert-stream.

Some of the better designs insert CHARs with a drop-shadow, so they are

readable over a wider range of backgrounds.

Teletext chipsets, and OnScreenDisplay chips, as others have mentioned, are a good design referance for the sync-side of things

-jg.

Reply to
-jg

No, in my design all the video processing is done in a processing clock domain that is bridged to the input video clock domain by asynchronous FIFOs. What you are describing should not be a problem in my system. Each pixel carries three flags: frame start, line start, and valid data. Video timing counters increment as appropriate when each of these flags is observed in a given video processing block.

I realize that lines need to be counted, and position in the current frame kept track of, and thus you need to know the number of valid/blank pixels and lines and count them while the system is online. But these parameters could be set as generics or package constants or even passed in to registers at run time (if we wanted the char-gen scheme to be resolution and timing agnostic).

This is the kind of block I am looking for. But it looks as if no-one knows of something like this floating around on the web.

Reply to
wallge

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.