119 lines
4.3 KiB
Verilog
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 |