Files
Imants Pulkstenis d18a10f6ea Initial commit
Uploading to GitHub
2019-07-11 18:01:21 +03:00

119 lines
4.3 KiB
Verilog

//
// i2c sender based on VHDL code:
// http://hamsterworks.co.nz/mediawiki/index.php/OV7670_camera
//
// main input clk for module 25MHz like other
// oc7670 top module modules of my design.
//
module i2c_sender (
input clk, // 25MHz input clk
inout ov7670_sda,
output reg ov7670_scl,
output reg taken,
input send,
input [7:0] id,
input [7:0] register,
input [7:0] value);
//------------- reg/wire declarations ------------------
reg [6:0] divider = 7'b0000001; // this value gives a 127 cycle pause before the initial frame is sent
reg [31:0] busy_sr = 32'h00000000;
reg [31:0] data_sr = 32'hffffffff;
reg [15:0] r_wait = 16'h0000;
reg r_wait_done = 0;
//----------- combinational logic ----------------------
assign ov7670_sda = ( busy_sr[11:10] == 2'b10 ||
busy_sr[20:19] == 2'b10 ||
busy_sr[29:28] == 2'b10 )?
1'bz : data_sr[31];
//---------- synchronous logic -------------------------
always@(posedge clk) begin
taken <= 1'b0;
if (busy_sr[31] == 1'b0) begin
ov7670_scl <= 1'b1;
if (send == 1) begin
if (divider == 7'b0000000 && r_wait_done == 1) begin
data_sr <= {3'b100 , id , 1'b0 , register , 1'b0 , value , 1'b0 , 2'b01};
busy_sr <= {3'b111 , 9'b111111111 , 9'b111111111 , 9'b111111111 , 2'b11};
taken <= 1;
end
else begin
if (r_wait < 16'hffff) begin
r_wait <= r_wait + 1; end // this only happens on powerup
else begin
r_wait_done <= 1;
divider <= 7'b0000000;
end
end
end
end
else begin
case ({busy_sr[(32-1):(32-3)] , busy_sr[2:0]})
{3'b111,3'b111} : // start seq #1
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b1;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b1;
endcase
{3'b111,3'b110} : // start seq #2
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b1;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b1;
endcase
{3'b111,3'b100} : // start seq #3
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b0;
2'b01 : ov7670_scl <= 1'b0;
2'b10 : ov7670_scl <= 1'b0;
default : ov7670_scl <= 1'b0;
endcase
{3'b110,3'b000} : // end seq #1
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b0;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b1;
endcase
{3'b100,3'b000} : // end seq #2
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b1;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b1;
endcase
{3'b000,3'b000} : // Idle
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b1;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b1;
endcase
default :
case (divider[6 : 5])
2'b00 : ov7670_scl <= 1'b0;
2'b01 : ov7670_scl <= 1'b1;
2'b10 : ov7670_scl <= 1'b1;
default : ov7670_scl <= 1'b0;
endcase
endcase
if (divider == 7'b1111111 ) begin
busy_sr <= {busy_sr[(32-2) : 0] , 1'b0};
data_sr <= {data_sr[(32-2) : 0] , 1'b1};
divider <= 7'b0000000;
end
else begin
divider <= divider + 1;
end
end
end
endmodule