Video Recording

 

UPDATES :

  • I can do a simple recording that doesn’t jump all over the place.
  • I can record and playback 8 bits over time and write that as a byte to the SRAM now.
  • I can record images in different banks of memory.
  • I can record two bit recordings with two colors.
  • I can record and playback in different resolutions
  • I haven’t successfully managed to record 8 images in parallel into the SRAM however.
  • I haven’t managed to record an “animation” yet.
  • Still no dice with the OV7670 camera.
  • I’ve got the HX4K FPGA programmed to blink and LED.

******

OK, I have got rpi recording working reliably šŸ™‚ I also played with different clock divisions, recorded with rpi clock and PB with the FPGA clock, tried recording animations (failed), and tried recording two images in different parts of SRAM.

My process so far : I keep the programmer plugged in but disconnect from the USB after uploading. I reset the FPGA after programming every time (unglug and replug in USB), and delete and recreate + deactivate and reactivate the recording device in OBS studio after unplugging and replugging in the USB each time. I’m using male-female jumpers to go from the rpi to the FPGA. The rpi is powered seperately. I’m using a VGA capture and OBS studio.

Left is the original (Green 5 in DPI mode) and right is the playback (inverted) from SRAM :

Here is the code :

module verilog(

input wire rec,
input wire clk,
input wire rpi_h_sync,
input wire rpi_v_sync,
input wire rpi_color,


output reg [17:0] addr,
inout wire [7:0] io,
output wire cs,
output reg we,
output wire oe,

output wire h_sync,
output wire v_sync,
output reg [3:0] r_out,
output reg [3:0] g_out,
output reg [3:0] b_out
);

assign cs = 0;
assign oe = 0;

assign h_sync = rpi_h_sync;

assign v_sync = rpi_v_sync;

wire [7:0] data_in;
wire [7:0] data_out;

assign data_in[7:0] = (rpi_color == 1'b1) ? 8'b11111111 : 8'b00000000; // color from rpi

reg [7:0] a, b;

assign io = (rec==0) ? a : 8'bzzzzzzzz;

assign data_out = b;


reg [3:0] counter = 0; //our clock divider

//SRAM address counter
always @(posedge clk) begin

counter <= counter + 1;

if (counter[2]) begin

if(rpi_v_sync) begin // reset the SRAM each time we draw a new frame
addr <= 0;
end

else begin
addr <= addr+1;
end
end
end

always @(posedge counter[2]) begin
b <= io;
a <= data_in;
if (rec==0) begin
we <= addr[0]; //not sure why it isn't the inverse of addr[0] but that doesn't make the inverse on 'scope
end
else begin
we <= 1;
end
end

always @(posedge counter[2]) begin


if ((rec==0) && (a==8'b11111111))
begin
r_out[0] <= 1'b0;
r_out[1] <= 1'b0;
r_out[2] <= 1'b0;

b_out[0] <= 1'b0;
b_out[1] <= 1'b0;
b_out[2] <= 1'b0;

g_out[0] <= 1'b0;
g_out[1] <= 1'b0;
g_out[2] <= 1'b0;
end

else if ((rec==0) && (a==8'b00000000))
begin
r_out[0] <= 1'b1;
r_out[1] <= 1'b1;
r_out[2] <= 1'b0;

b_out[0] <= 1'b1;
b_out[1] <= 1'b1;
b_out[2] <= 1'b0;

g_out[0] <= 1'b1;
g_out[1] <= 1'b1;
g_out[2] <= 1'b0;
end

else if ((rec==1) && (b==8'b11111111)) //data_out not b ??
begin
r_out[0] <= 1'b1;
r_out[1] <= 1'b0;
r_out[2] <= 1'b1;

b_out[0] <= 1'b1;
b_out[1] <= 1'b0;
b_out[2] <= 1'b1;

g_out[0] <= 1'b1;
g_out[1] <= 1'b0;
g_out[2] <= 1'b1;
end
else
begin
r_out[0] <= 1'b1;
r_out[1] <= 1'b0;
r_out[2] <= 1'b0;

b_out[0] <= 1'b1;
b_out[1] <= 1'b0;
b_out[2] <= 1'b0;

g_out[0] <= 1'b1;
g_out[1] <= 1'b0;
g_out[2] <= 1'b0;
end
end


endmodule

And the constraints :

set_io clk 58

set_io rpi_h_sync 62
set_io rpi_v_sync 61
set_io rpi_color 52

set_io h_sync 76
set_io v_sync 97

set_io rec 47

set_io r_out[0] 91 //for vga
set_io r_out[1] 95 //for vga
set_io r_out[2] 96 //for vga

set_io b_out[0] 87 //for vga
set_io b_out[1] 88 //for vga
set_io b_out[2] 90 //for vga

set_io g_out[0] 75 //for vga
set_io g_out[1] 74 //for vga
set_io g_out[2] 73 //for vga

set_io io[0] 7
set_io io[1] 8
set_io io[2] 9
set_io io[3] 10
set_io io[4] 11
set_io io[5] 12
set_io io[6] 19
set_io io[7] 22

set_io addr[0] 4
set_io addr[1] 3
set_io addr[2] 2
set_io addr[3] 1
set_io addr[4] 144
set_io addr[5] 143
set_io addr[6] 142
set_io addr[7] 141
set_io addr[8] 120
set_io addr[9] 121
set_io addr[10] 24
set_io addr[11] 122
set_io addr[12] 135
set_io addr[13] 119
set_io addr[14] 134
set_io addr[15] 116
set_io addr[16] 129
set_io addr[17] 128


set_io cs 25
set_io oe 23
set_io we 118

And here are some of the documents that were helpful :

   

***

Using the only working Arduino library I could find I can get a kind of VGA out of the OV7670 but it remains extremely slow.