I'd like to be able to tell it: write those 37 bytes to that slave
address...or read 48 bytes from that slave address...
I thought I'd ask before starting to write the state machine!
Thanks,
Diego
---------------------------------------
This message was sent using the comp.arch.fpga web interface on
http://www.FPGARelated.com
Hi,
I want to use the core in Master mode, one slave address (although it's
easy to make this programmable). I'm more after the sate machine that would
take care of the 'byte level' transfer and make it look more like macro I2C
transaction.
Verilog ideally, but I can deal with both. It's on an FPGA.
Thanks for the help.
It's probably more code than you want to look at.
And it's VHDL. I'm not sure how Verilog supports
constructs like the enum but I believe you could
use another numbering system in Verilog and code
the ACK and STOP with separate if statements.
One thing that helped me set up my state machine
was to make the I2C clock always change on the
same clock phase edges. Then the START and STOP
conditions were set up by changing the data signal
on the other edges.
On the top level I used a Xilink IO tristate buffer
with the Input connected to ground, and the tristate
connected to the outgoing data. This allows the output
pin to be pulled up by an external resistor on your
board as specified by the I2C standard.
Good luck and tell us how it's going.
Brad Smallridge
AiVision
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity i2c8 is
port(
clk : in std_logic;
en : in std_logic;
reset : in std_logic;
sda_master : out std_logic;
scl_master : out std_logic;
sda_slave : in std_logic;
scl_slave : in std_logic;
ack_error : out std_logic;
hold_error : out std_logic );
end i2c8;
architecture Behavioral of i2c8 is
signal i2c_clk_phase0 : unsigned(1 downto 0);
signal i2c_clk_phase1 : unsigned(1 downto 0);
signal i2c_clk_phase2 : unsigned(1 downto 0);
signal i2c_bit_index0 : unsigned(2 downto 0);
signal i2c_bit_index1 : unsigned(2 downto 0);
signal i2c_bit_index2 : unsigned(2 downto 0);
type i2c_enum is (
h00,h01,h02,h03,h04,h05,h06,h07,h08,h09,h0A,h0B,h0C,h0D,h0E,h0F,
h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,h1A,h1B,h1C,h1D,h1E,h1F,
h20,h21,h22,h23,h24,h25,h26,h27,h28,h29,h2A,h2B,h2C,h2D,h2E,h2F,
h30,h31,h32,h33,h34,h35,h36,h37,h38,h39,h3A,h3B,h3C,h3D,h3E,h3F,
h40,h41,h42,h43,h44,h45,h46,h47,h48,h49,h4A,h4B,h4C,h4D,h4E,h4F,
h50,h51,h52,h53,h54,h55,h56,h57,h58,h59,h5A,h5B,h5C,h5D,h5E,h5F,
h60,h61,h62,h63,h64,h65,h66,h67,h68,h69,h6A,h6B,h6C,h6D,h6E,h6F,
h70,h71,h72,h73,h74,h75,h76,h77,h78,h79,h7A,h7B,h7C,h7D,h7E,h7F,
h80,h81,h82,h83,h84,h85,h86,h87,h88,h89,h8A,h8B,h8C,h8D,h8E,h8F,
h90,h91,h92,h93,h94,h95,h96,h97,h98,h99,h9A,h9B,h9C,h9D,h9E,h9F,
hA0,hA1,hA2,hA3,hA4,hA5,hA6,hA7,hA8,hA9,hAA,hAB,hAC,hAD,hAE,hAF,
hB0,hB1,hB2,hB3,hB4,hB5,hB6,hB7,hB8,hB9,hBA,hBB,hBC,hBD,hBE,hBF,
hC0,hC1,hC2,hC3,hC4,hC5,hC6,hC7,hC8,hC9,hCA,hCB,hCC,hCD,hCE,hCF,
hD0,hD1,hD2,hD3,hD4,hD5,hD6,hD7,hD8,hD9,hDA,hDB,hDC,hDD,hDE,hDF,
hE0,hE1,hE2,hE3,hE4,hE5,hE6,hE7,hE8,hE9,hEA,hEB,hEC,hED,hEE,hEF,
hF0,hF1,hF2,hF3,hF4,hF5,hF6,hF7,hF8,hF9,hFA,hFB,hFC,hFD,hFE,hFF,
START,STOP,ACK,HALT,REPEAT ) ;
signal i2c_data1 : i2c_enum ;
signal i2c_data2 : i2c_enum ;
signal i2c_data_vector : unsigned( 8 downto 0) ;
type i2c_array_type is array(natural range <>) of i2c_enum;
constant i2c_data_array : i2c_array_type :=(
-- START,h88,ACK,h00,ACK,h00,ACK,STOP, -- Status 0 VER2-0 CCRDO CCRDE 0 FSEQ
O_E
-- START,h88,ACK,h00,ACK,h00,ACK,STOP, -- Null 01H to 25H
START,h88,ACK,h26,ACK,h00,ACK,STOP, -- Wide screen WSS7-0
START,h88,ACK,h27,ACK,h00,ACK,STOP, -- Wide screen WSSON 0 WSS13-8
START,h88,ACK,h28,ACK,h19,ACK,STOP, -- DECCOL DECFIS BS[5:0]=19H NTSC
START,h88,ACK,h29,ACK,h1D,ACK,STOP, -- 0 0 BE[5:0]=1DH
START,h88,ACK,h2A,ACK,h00,ACK,STOP, -- Copy generation CG07-0
START,h88,ACK,h2B,ACK,h00,ACK,STOP, -- CG15-08
START,h88,ACK,h2C,ACK,h00,ACK,STOP, -- CGEN 0 0 0 CG19-16
START,h88,ACK,h2D,ACK,hFF,ACK,STOP, -- CVBSEN1 CVBSEN0 CVBSTRI YTRI
-- CTRI RTRI GTRI BTRI
-- h2E to h37 -- Null
START,h88,ACK,h38,ACK,h1A,ACK,STOP, -- Gain luminance for RGB 0 0 0 GY4-0
START,h88,ACK,h39,ACK,h1A,ACK,STOP, -- Gain colour diff for RGB 0 0 0
GCD4-0
-- Turning this off created hsync and color issues, need SYMP
START,h88,ACK,h3A,ACK,h13,ACK,STOP, -- 0 CBENB Colour Bar Enable
-- 0
-- 0
-- SYMP Synchs from 656 Header
-- DEMOFF Dematrix OFF
-- CSYNC Advanced Composite Sync
-- MP2C MPEG straight binary (default
ON)
-- VP2C Fader is straight binary
(default ON)
START,h88,ACK,h42,ACK,h00,ACK,STOP, -- KEY1LU 7-0
START,h88,ACK,h43,ACK,h00,ACK,STOP, -- KEY1LV 7-0
START,h88,ACK,h44,ACK,h00,ACK,STOP, -- KEY1LY 7-0
START,h88,ACK,h45,ACK,h00,ACK,STOP, -- KEY2LU 7-0
START,h88,ACK,h46,ACK,h00,ACK,STOP, -- KEY2LV 7-0
START,h88,ACK,h47,ACK,h00,ACK,STOP, -- KEY2LY 7-0
START,h88,ACK,h48,ACK,h00,ACK,STOP, -- KEY1UU 7-0
START,h88,ACK,h49,ACK,h00,ACK,STOP, -- KEY1UV 7-0
START,h88,ACK,h4A,ACK,h00,ACK,STOP, -- KEY1UY 7-0
START,h88,ACK,h4B,ACK,h00,ACK,STOP, -- KEY2UU 7-0
START,h88,ACK,h4C,ACK,h00,ACK,STOP, -- KEY2UV 7-0
START,h88,ACK,h4D,ACK,h00,ACK,STOP, -- KEY2UY 7-0
START,h88,ACK,h4E,ACK,h00,ACK,STOP, -- 0 0 FADE1 5-0
START,h88,ACK,h4F,ACK,h00,ACK,STOP, -- CFADEM CFADEV FADE2 5-0
START,h88,ACK,h50,ACK,h00,ACK,STOP, -- 0 0 FADE3 5-0
START,h88,ACK,h51,ACK,h40,ACK,STOP, -- LUTU 7-0
START,h88,ACK,h52,ACK,h80,ACK,STOP, -- LUTV 7-0
START,h88,ACK,h53,ACK,hA0,ACK,STOP, -- LUTY 7-0
START,h88,ACK,h54,ACK,h0C,ACK,STOP, -- VPSEN 0 ENCIN RGBIN
-- DELIN VPSEL EDGE2 EDGE1
START,h88,ACK,h55,ACK,h00,ACK,STOP, -- VPS byte 5 VPS5 7-0
START,h88,ACK,h56,ACK,h00,ACK,STOP, -- VPS byte 11 VPS11 7-0
START,h88,ACK,h57,ACK,h00,ACK,STOP, -- VPS byte 12 VPS12 7-0
START,h88,ACK,h58,ACK,h00,ACK,STOP, -- VPS byte 13 VPS13 7-0
START,h88,ACK,h59,ACK,h00,ACK,STOP, -- VPS byte 14 VPS14 7-0
START,h88,ACK,h5A,ACK,h35,ACK,STOP, -- Chrominance phase
START,h88,ACK,h5B,ACK,h76,ACK,STOP, -- Gain U=076 with the 0 in 5D.7
START,h88,ACK,h5C,ACK,h65,ACK,STOP, -- Gain V=165 with the 1 in 5E.7
START,h88,ACK,h5D,ACK,h7A,ACK,STOP, -- GAINU8 DECOE BLCKL=3A
START,h88,ACK,h5E,ACK,hAE,ACK,STOP, -- GAINV8 DECPH BLNNL=3A
START,h88,ACK,h5F,ACK,h2E,ACK,STOP, -- CCRS1-0 BLNVB=3A
-- h60 -- Null
START,h88,ACK,h61,ACK,h15,ACK,STOP, -- DOWNB DOWNA INPI YGS
-- SECAM SCBW PAL FISE
-- 7 DOWNB 0 = DACs for R, G and B in normal operational mode
-- 1 = DACs for R, G and B forced to lowest output voltage;
-- default state after reset.
-- 6 DOWNA 0 = DACs for CVBS, Y and C in normal operational mode;
-- default state after reset.
-- 1 = DACs for CVBS, Y and C forced to lowest output voltage
-- 5 INPI 0 = PAL switch phase is nominal; default state after reset
-- 1 = PAL switch phase is inverted compared to nominal
-- if RTC is enabled; see Table 43
-- 4 YGS 0 = luminance gain for white - black 100 IRE;
-- default state after reset
-- 1 = luminance gain for white - black 92.5
-- IRE including 7.5 IRE set-up of black
-- 3 SECAM 0 = no SECAM encoding; default state after reset
-- 1 = SECAM encoding activated; bit PAL has to be set to logic 0
-- 2 SCBW 0 = enlarged bandwidth for chrominance encoding
-- 1 = standard bandwidth for chrominance encoding
-- default state after reset
-- 1 PAL 0 = NTSC encoding (non-alternating V component)
-- 1 = PAL encoding (alternating V component); default
-- 0 FISE 0 = 864 total pixel clocks per line; PAL default
-- 1 = 858 total pixel clocks per line NTSC
START,h88,ACK,h62,ACK,h3F,ACK,STOP, -- RTCE, BurST Amplitude=3FH
-- NTSC-M: fsc = 227.5, fllc = 1716 FSC = d569408543 h21F07C1F
START,h88,ACK,h63,ACK,h1F,ACK,STOP, -- Subcarrier 0 FSC 07-00
START,h88,ACK,h64,ACK,h7C,ACK,STOP, -- Subcarrier 1 FSC 15-08
START,h88,ACK,h65,ACK,hF0,ACK,STOP, -- Subcarrier 2 FSC 23-16
START,h88,ACK,h66,ACK,h21,ACK,STOP, -- Subcarrier 3 FSC 31-24
START,h88,ACK,h67,ACK,h00,ACK,STOP, -- Line 21 odd 0 L21O0 7-0
START,h88,ACK,h68,ACK,h00,ACK,STOP, -- Line 21 odd 1 L21O1 7-0
START,h88,ACK,h69,ACK,h00,ACK,STOP, -- Line 21 even 0 L21E0 7-0
START,h88,ACK,h6A,ACK,h00,ACK,STOP, -- Line 21 even 1 L21E1 7-0
START,h88,ACK,h6B,ACK,h00,ACK,STOP, -- SRCV11-10 TRCV2 ORCV1
-- PRCV1 CBLF ORCV2 PRCV2
START,h88,ACK,h6C,ACK,hF0,ACK,STOP, -- HTRIG7-0
START,h88,ACK,h6D,ACK,h00,ACK,STOP, -- HTRIG10-8 VTRIG4-0
START,h88,ACK,h6E,ACK,h80,ACK,STOP, -- SBLBN BLCKON PHRES1-0 LDEL1-0 FLC1-0
START,h88,ACK,h6F,ACK,h00,ACK,STOP, -- CCEN1 CCEN0 TTXEN SCCLN4-0
START,h88,ACK,h70,ACK,h00,ACK,STOP, -- RCV2 output start RCV2S7-0
START,h88,ACK,h71,ACK,h00,ACK,STOP, -- RCV2 output end RCV2E7-E0
START,h88,ACK,h72,ACK,h00,ACK,STOP, -- 0 RCV2E10-8 0 RCV2S10-8
START,h88,ACK,h73,ACK,h54,ACK,STOP, -- TTX request H start TTXHS 7-0
START,h88,ACK,h74,ACK,h02,ACK,STOP, -- TTX request H delay TTXHD 7-0
START,h88,ACK,h75,ACK,h83,ACK,STOP, -- CSYNCA4-0 VS_S2-0
START,h88,ACK,h76,ACK,h06,ACK,STOP, -- TTXOVS 7-0
START,h88,ACK,h77,ACK,h10,ACK,STOP, -- TTXOVE 7-0
START,h88,ACK,h78,ACK,h05,ACK,STOP, -- TTXEVS 7-0
START,h88,ACK,h79,ACK,h10,ACK,STOP, -- TTXEVE 7-0
START,h88,ACK,h7A,ACK,h25,ACK,STOP, -- First active line FAL 7-0
START,h88,ACK,h7B,ACK,hFE,ACK,STOP, -- Last active line LAL 7-0
START,h88,ACK,h7C,ACK,h00,ACK,STOP, -- TTX mode
-- MSB vertical
-- TTX60
-- LAL8
-- TTXO
-- FAL8
-- TTXEVE8 TTXOVE8 TTXEVS8 TTXOVS8
-- h7D -- Null
START,h88,ACK,h7E,ACK,h00,ACK,STOP, -- Disable TTX line LINE 12-5
START,h88,ACK,h7F,ACK,h00,ACK,STOP, -- Disable TTX line LINE 20-13
HALT );
subtype i2c_dat_index_type is natural;
signal i2c_dat_index0 : i2c_dat_index_type;
signal i2c_dat_index1 : i2c_dat_index_type;
begin
i2c_clock_phase_index_proc : process(clk)
begin
if( clk'event and clk='1') then
if( reset='1' ) then
i2c_clk_phase0 <= (others=>'0');
i2c_bit_index0 <= (others=>'0');
i2c_dat_index0 <= 0;
elsif(en='1') then
if( i2c_clk_phase0="11" ) then
i2c_clk_phase0 <= (others=>'0');
if( i2c_data1=HALT ) then
null;
elsif( i2c_data1=REPEAT ) then
i2c_clk_phase0 <= (others=>'0');
i2c_bit_index0 <= (others=>'0');
i2c_dat_index0 <= 0;
elsif( i2c_data1=START
or i2c_data1=STOP
or i2c_data1=ACK
or i2c_bit_index0="111" ) then
i2c_bit_index0 <= (others=>'0');
i2c_dat_index0 <= i2c_dat_index0 + 1 ;
else
i2c_bit_index0 <= i2c_bit_index0+1;
end if;
else
i2c_clk_phase0 <= i2c_clk_phase0+1;
end if;
i2c_clk_phase1 <= i2c_clk_phase0;
i2c_clk_phase2 <= i2c_clk_phase1;
i2c_bit_index1 <= i2c_bit_index0;
i2c_bit_index2 <= i2c_bit_index1;
i2c_dat_index1 <= i2c_dat_index0;
end if;
end if;
end process;
i2c_bram_proc : process(clk)
begin
if( clk'event and clk='1') then
if(en='1')then
-- i2c_data1 <= i2c_data_array(to_integer(i2c_dat_index0));
i2c_data1 <= i2c_data_array(i2c_dat_index0);
i2c_data2 <= i2c_data1;
end if;
end if;
end process;
i2c_vector_proc: process(i2c_data1)
begin
i2c_data_vector <= to_unsigned(i2c_enum'pos(i2c_data1),9);
end process;
i2c_proc:process(clk)
begin
if( clk'event and clk='1') then
if(reset='1') then
scl_master <= '1';
sda_master <= '1';
ack_error <= '0';
hold_error <= '0';
elsif(en='1') then
if( i2c_clk_phase1="00" ) then
scl_master <= '0';
elsif( i2c_clk_phase1="01" ) then
if( i2c_data1=STOP ) then
sda_master <= '0';
elsif( i2c_data1=ACK
or i2c_data1=START
or i2c_data1=HALT
or i2c_data1=REPEAT ) then
sda_master <= '1';
else
-- for all the h enumerated numerics
case i2c_bit_index1 is
when "000" => sda_master <= i2c_data_vector(7) ;
when "001" => sda_master <= i2c_data_vector(6) ;
when "010" => sda_master <= i2c_data_vector(5) ;
when "011" => sda_master <= i2c_data_vector(4) ;
when "100" => sda_master <= i2c_data_vector(3) ;
when "101" => sda_master <= i2c_data_vector(2) ;
when "110" => sda_master <= i2c_data_vector(1) ;
when "111" => sda_master <= i2c_data_vector(0) ;
when others => null ;
end case;
end if;
elsif( i2c_clk_phase1="10" ) then
scl_master <= '1';
-- Check for ACKnowledge from slave device
-- The slave device should pull the sda line low
if( i2c_data1=ACK and sda_slave='1') then
ack_error <= '1';
end if;
elsif( i2c_clk_phase1="11" ) then
if( i2c_data1=START ) then
sda_master <= '0';
elsif( i2c_data1=STOP ) then
sda_master <= '1';
end if;
if( scl_slave='0' ) then
hold_error <= '1';
end if;
end if;
end if;
end if;
end process;
end Behavioral;
Hi,
Thanks a lot for the code. However, this seems more like a replacement for
the opencores.org I2C master core!
I was wanting to use this core since it supports all the
'harder-to-support' I2C specifications and it has been debugged for quite a
while now. The only problem is that it only brings things up to the 'byte'
level. There still needs to be a fair level of handshaking and pooling in
order to generate a transfer of the type'write ABCD at address 08'.
Anyone has done it with a picoblaze? This would seem like quite a nice way
to go...
Might be. But I didn't look at opencores.
> I was wanting to use this core since it supports all the
> 'harder-to-support' I2C specifications and it has been debugged for quite
> a
> while now. The only problem is that it only brings things up to the 'byte'
> level. There still needs to be a fair level of handshaking and pooling in
> order to generate a transfer of the type'write ABCD at address 08'.
You would simply put this in your data array:
START,h08,ACK,hAB,ACK,hCD,ACK,STOP,
Not sure what else you need. You don't say.
Brad Smallridge
Ai Vision