// File i2c_sender.vhd translated with vhd2vl v2.0 VHDL to Verilog

//
//
//
//
//
//
//
//
//
File i2c_sender.vhd translated with vhd2vl v2.0 VHDL to Verilog RTL translator
Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd - http://www.ocean-logic.com
Modifications (C) 2006 Mark Gonzales - PMC Sierra Inc
vhd2vl comes with ABSOLUTELY NO WARRANTY
ALWAYS RUN A FORMAL VERIFICATION TOOL TO COMPARE VHDL INPUT TO VERILOG OUTPUT
This is free software, and you are welcome to redistribute it under certain conditions.
See the license file license.txt included with the source for details.
//-------------------------------------------------------------------------------// Engineer:
Mike Field <[email protected]>
//
// Module Name: i2c_sender h- Behavioral
//
// Description: Send register writes over an I2C-like interface
//
// Feel free to use this how you see fit, and fix any errors you find :-)
//-------------------------------------------------------------------------------module i2c_sender(
clk,
resend,
sioc,
siod
);
input clk;
input resend;
output sioc;
//inout siod;
output siod;
wire
wire
reg
reg
clk;
resend;
sioc;
siod;
reg [8:0] divider = 0;
// this value gives nearly 200ms cycles before the first register is written
reg [7:0] initial_pause = 0;
reg finished = 0;
reg [7:0] address = 0;
reg [28:0] clk_first_quarter = 29'h1FFFFFFF; // := (others => '1');
reg [28:0] clk_last_quarter = 29'h1FFFFFFF; // := (others => '1');
reg [28:0] busy_sr = 29'h1FFFFFFF; // := (others => '1');
reg [28:0] data_sr = 29'h1FFFFFFF; // := (others => '1');
reg [28:0] tristate_sr = 0;
reg [15:0] reg_value = 0;
parameter i2c_wr_addr = 8'h72;
//type reg_value_pair is ARRAY(0 TO 63) OF std_logic_vector(15 DOWNTO 0);
parameter [0:0]
array = 0;
wire [15:0] reg_value_pairs [0:63] = {
//
initial
//
begin
//
------------------//
-- Powerup please!
//
------------------//reg_value_pairs[0] = 16'h4110;
16'h4110,
//
--------------------------------------//
-- These valuse must be set as follows
//
--------------------------------------16'h9803, 16'h9AE0, 16'h9C30, 16'h9D61, 16'hA2A4,
16'hA3A4, 16'hE0D0, 16'h5512, 16'hF900,
//reg_value_pairs[1] = 16'h9803;
//reg_value_pairs[2] = 16'h9AE0;
//
//
--------------//
-- Input mode
//
--------------16'h1506, // YCbCr 422, DDR, External sync
16'h4810, // Left justified data (D23 downto 8)
//
according to documenation, style 2 should be 16'h1637 but it isn't. ARGH!
16'h1637, // 444 output, 8 bit style 2, 1st half on rising edge - YCrCb clipping
16'h1700, // output asp ect ratio 16:9, external DE
16'hD03C, // auto sync data - must be set for DDR modes. No DDR clock delay
---------------- Output mode
--------------16'hAF04, // DVI mode
16'h4c04, // Deep colour off (HDMI only?)
- not needed
16'h4000, // Turn off additional data packets - not needed
//
//
//
//
//
//
//
//
//
--------------------------------------------------------------- Here is the YCrCb => RGB conversion, as per programming guide
-- This is table 57 - HDTV YCbCr (16 to 255) to RGB (0 to 255)
--------------------------------------------------------------- (Cr * A1
+
Y * A2
+
Cb * A3)/4096 +
A4
= Red
16'h18E7, 16'h1934,
16'h1A04, 16'h1BAD,
16'h1C00, 16'h1D00,
16'h1E1C, 16'h1F1B,
-- (Cr * B1
+
Y * B2
+
Cb * B3)/4096 +
B4
= Green
16'h201D, 16'h21DC,
16'h2204, 16'h23AD,
16'h241F, 16'h2524,
16'h2601, 16'h2735,
-- (Cr * C1
+
Y * C2
+
Cb * C3)/4096 +
C4
= Blue
16'h2800, 16'h2900,
16'h2A04, 16'h2BAD,
16'h2C08, 16'h2D7C,
16'h2E1B, 16'h2F77,
//
//
//
//
//
};
-- Extra space filled with FFFFs to signify end
16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF,
16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF,
16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF, 16'hFFFF,
);
always @(posedge clk) begin
reg_value <= reg_value_pairs[address] ;
end
always @(data_sr or tristate_sr) begin
if(tristate_sr[28] == 1'b 0) begin
siod <= data_sr[28] ;
end
else begin
siod <= 1'bz;
end
end
of data
16'hFFFF, 16'hFFFF,
16'hFFFF, 16'hFFFF, 16'hFFFF,
16'hFFFF, 16'hFFFF
always @(*) begin
case(divider[8:7] )
2'b 00 : sioc <= clk_first_quarter[28] ;
2'b 11 : sioc <= clk_last_quarter[28] ;
default : sioc <= 1'b 1;
endcase
end
always @(posedge clk) begin
if(resend == 1'b 1) begin
address <= {8{1'b0}};
clk_first_quarter <= {29{1'b1}};
clk_last_quarter <= {29{1'b1}};
busy_sr <= {29{1'b0}};
divider <= {9{1'b0}};
initial_pause <= {8{1'b0}};
finished <= 1'b 0;
end
if(busy_sr[28] == 1'b 0) begin
if(initial_pause[7] == 1'b 0) begin
initial_pause <= initial_pause + 1;
end
else if(finished == 1'b 0) begin
if(divider == 8'b 11111111) begin
divider <= {9{1'b0}};
if(reg_value[15:8] == 8'b 11111111) begin
finished <= 1'b 1;
end
else begin
// move the new data into the shift registers
clk_first_quarter <= {29{1'b0}};
clk_first_quarter[28] <= 1'b 1;
clk_last_quarter <= {29{1'b0}};
clk_last_quarter[0] <= 1'b 1;
//
Start
Address
Ack
Register
Ack
Value
Stop
tristate_sr <= {1'b 0,8'b 00000000,1'b 1,8'b 00000000,1'b 1,8'b 00000000,1'b 1,1'b 0};
data_sr <= {1'b 0,i2c_wr_addr,1'b 1,reg_value[15:8] ,1'b 1,reg_value[7:0] ,1'b 1,1'b 0};
Ack
busy_sr <= {29{1'b1}};
address <= (address + 1);
end
end
else begin
divider <= divider + 1;
end
end
end
else begin
if(divider == 8'b 11111111) begin
// divide clkin by 256 for I2C
tristate_sr <= {tristate_sr[27:0] ,1'b 0};
busy_sr <= {busy_sr[27:0] ,1'b 0};
data_sr <= {data_sr[27:0] ,1'b 1};
clk_first_quarter <= {clk_first_quarter[27:0] ,1'b 1};
clk_last_quarter <= {clk_last_quarter[27:0] ,1'b 1};
divider <= {9{1'b0}};
end
else begin
divider <= divider + 1;
end
end
end
endmodule