Line 35... |
Line 35... |
---- ----
|
---- ----
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
-- CVS Log
|
-- CVS Log
|
--
|
--
|
-- $Id: i2c_master_top.vhd,v 1.3 2002-11-30 22:24:37 rherveille Exp $
|
-- $Id: i2c_master_top.vhd,v 1.4 2002-12-26 16:05:47 rherveille Exp $
|
--
|
--
|
-- $Date: 2002-11-30 22:24:37 $
|
-- $Date: 2002-12-26 16:05:47 $
|
-- $Revision: 1.3 $
|
-- $Revision: 1.4 $
|
-- $Author: rherveille $
|
-- $Author: rherveille $
|
-- $Locker: $
|
-- $Locker: $
|
-- $State: Exp $
|
-- $State: Exp $
|
--
|
--
|
-- Change History:
|
-- Change History:
|
-- $Log: not supported by cvs2svn $
|
-- $Log: not supported by cvs2svn $
|
|
-- Revision 1.3 2002/11/30 22:24:37 rherveille
|
|
-- Cleaned up code
|
|
--
|
-- Revision 1.2 2001/11/10 10:52:44 rherveille
|
-- Revision 1.2 2001/11/10 10:52:44 rherveille
|
-- Changed PRER reset value from 0x0000 to 0xffff, conform specs.
|
-- Changed PRER reset value from 0x0000 to 0xffff, conform specs.
|
--
|
--
|
|
|
|
|
Line 104... |
Line 107... |
|
|
-- output signals
|
-- output signals
|
cmd_ack : out std_logic;
|
cmd_ack : out std_logic;
|
ack_out : out std_logic;
|
ack_out : out std_logic;
|
i2c_busy : out std_logic;
|
i2c_busy : out std_logic;
|
|
i2c_al : out std_logic;
|
dout : out std_logic_vector(7 downto 0);
|
dout : out std_logic_vector(7 downto 0);
|
|
|
-- i2c lines
|
-- i2c lines
|
scl_i : in std_logic; -- i2c clock line input
|
scl_i : in std_logic; -- i2c clock line input
|
scl_o : out std_logic; -- i2c clock line output
|
scl_o : out std_logic; -- i2c clock line output
|
Line 127... |
Line 131... |
signal sr : std_logic_vector(7 downto 0); -- status register
|
signal sr : std_logic_vector(7 downto 0); -- status register
|
|
|
-- internal reset signal
|
-- internal reset signal
|
signal rst_i : std_logic;
|
signal rst_i : std_logic;
|
|
|
|
-- wishbone write access
|
|
signal wb_wacc : std_logic;
|
|
|
-- internal acknowledge signal
|
-- internal acknowledge signal
|
signal iack_o : std_logic;
|
signal iack_o : std_logic;
|
|
|
-- done signal: command completed, clear command register
|
-- done signal: command completed, clear command register
|
signal done : std_logic;
|
signal done : std_logic;
|
|
|
-- command register signals
|
-- command register signals
|
signal sta, sto, rd, wr, ack, iack : std_logic;
|
signal sta, sto, rd, wr, ack, iack : std_logic;
|
|
|
-- core enable signal
|
signal core_en : std_logic; -- core enable signal
|
signal core_en : std_logic;
|
signal ien : std_logic; -- interrupt enable signal
|
signal ien : std_logic;
|
|
|
|
-- status register signals
|
-- status register signals
|
signal irxack, rxack : std_logic; -- received aknowledge from slave
|
signal irxack, rxack : std_logic; -- received aknowledge from slave
|
signal tip : std_logic; -- transfer in progress
|
signal tip : std_logic; -- transfer in progress
|
signal irq_flag : std_logic; -- interrupt pending flag
|
signal irq_flag : std_logic; -- interrupt pending flag
|
signal i2c_busy : std_logic; -- bus busy (start signal detected)
|
signal i2c_busy : std_logic; -- i2c bus busy (start signal detected)
|
|
signal i2c_al, al : std_logic; -- arbitration lost
|
|
|
begin
|
begin
|
-- generate internal reset signal
|
-- generate internal reset signal
|
rst_i <= arst_i xor ARST_LVL;
|
rst_i <= arst_i xor ARST_LVL;
|
|
|
Line 157... |
Line 164... |
begin
|
begin
|
if (wb_clk_i'event and wb_clk_i = '1') then
|
if (wb_clk_i'event and wb_clk_i = '1') then
|
iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored
|
iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored
|
end if;
|
end if;
|
end process gen_ack_o;
|
end process gen_ack_o;
|
|
|
wb_ack_o <= iack_o;
|
wb_ack_o <= iack_o;
|
|
|
|
|
|
-- generate wishbone write access signal
|
|
wb_wacc <= wb_cyc_i and wb_stb_i and wb_we_i;
|
|
|
-- assign wb_dat_o
|
-- assign wb_dat_o
|
assign_dato : process(wb_clk_i)
|
assign_dato : process(wb_clk_i)
|
begin
|
begin
|
if (wb_clk_i'event and wb_clk_i = '1') then
|
if (wb_clk_i'event and wb_clk_i = '1') then
|
case wb_adr_i is
|
case wb_adr_i is
|
Line 184... |
Line 193... |
end case;
|
end case;
|
end if;
|
end if;
|
end process assign_dato;
|
end process assign_dato;
|
|
|
|
|
-- registers block
|
-- generate registers (CR, SR see below)
|
regs_block: process(rst_i, wb_clk_i)
|
gen_regs: process(rst_i, wb_clk_i)
|
begin
|
begin
|
if (rst_i = '0') then
|
if (rst_i = '0') then
|
prer <= (others => '1');
|
prer <= (others => '1');
|
ctr <= (others => '0');
|
ctr <= (others => '0');
|
txr <= (others => '0');
|
txr <= (others => '0');
|
cr <= (others => '0');
|
|
elsif (wb_clk_i'event and wb_clk_i = '1') then
|
elsif (wb_clk_i'event and wb_clk_i = '1') then
|
if (wb_rst_i = '1') then
|
if (wb_rst_i = '1') then
|
prer <= (others => '1');
|
prer <= (others => '1');
|
ctr <= (others => '0');
|
ctr <= (others => '0');
|
txr <= (others => '0');
|
txr <= (others => '0');
|
cr <= (others => '0');
|
elsif (wb_wacc = '1') then
|
else
|
case wb_adr_i is
|
if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_we_i = '1') then
|
when "000" => prer( 7 downto 0) <= unsigned(wb_dat_i);
|
if (wb_adr_i(2) = '0') then
|
when "001" => prer(15 downto 8) <= unsigned(wb_dat_i);
|
case wb_adr_i(1 downto 0) is
|
when "010" => ctr <= wb_dat_i;
|
when "00" => prer( 7 downto 0) <= unsigned(wb_dat_i);
|
when "011" => txr <= wb_dat_i;
|
when "01" => prer(15 downto 8) <= unsigned(wb_dat_i);
|
|
when "10" => ctr <= wb_dat_i;
|
|
when "11" => txr <= wb_dat_i;
|
|
|
|
-- illegal cases, for simulation only
|
-- illegal cases, for simulation only
|
when others =>
|
when others =>
|
report ("Illegal write address, setting all registers to unknown.");
|
report ("Illegal write address, setting all registers to unknown.");
|
prer <= (others => 'X');
|
prer <= (others => 'X');
|
ctr <= (others => 'X');
|
ctr <= (others => 'X');
|
txr <= (others => 'X');
|
txr <= (others => 'X');
|
end case;
|
end case;
|
elsif ( (core_en = '1') and (wb_adr_i(1 downto 0) = 0) ) then
|
end if;
|
-- only take new commands when i2c ore enabled
|
end if;
|
|
end process gen_regs;
|
|
|
|
|
|
-- generate command register
|
|
gen_cr: process(rst_i, wb_clk_i)
|
|
begin
|
|
if (rst_i = '0') then
|
|
cr <= (others => '0');
|
|
elsif (wb_clk_i'event and wb_clk_i = '1') then
|
|
if (wb_rst_i = '1') then
|
|
cr <= (others => '0');
|
|
elsif (wb_wacc = '1') then
|
|
if ( (core_en = '1') and (wb_adr_i = 4) ) then
|
|
-- only take new commands when i2c core enabled
|
-- pending commands are finished
|
-- pending commands are finished
|
cr <= wb_dat_i;
|
cr <= wb_dat_i;
|
end if;
|
end if;
|
else
|
else
|
-- clear command bits when done
|
if (done = '1' or i2c_al = '1') then
|
if (done = '1') then
|
cr(7 downto 4) <= (others => '0'); -- clear command bits when command done
|
cr(7 downto 4) <= (others => '0');
|
-- or arbitration lost
|
end if;
|
end if;
|
|
|
-- reserved bits
|
cr(2 downto 1) <= (others => '0'); -- reserved bits, always '0'
|
cr(2 downto 1) <= (others => '0');
|
cr(0) <= '0'; -- clear IRQ_ACK bit
|
|
|
-- clear iack when irq_flag cleared
|
|
cr(0) <= cr(0) and irq_flag;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process gen_cr;
|
end process regs_block;
|
|
|
|
|
|
-- decode command register
|
-- decode command register
|
sta <= cr(7);
|
sta <= cr(7);
|
sto <= cr(6);
|
sto <= cr(6);
|
rd <= cr(5);
|
rd <= cr(5);
|
Line 249... |
Line 263... |
-- decode control register
|
-- decode control register
|
core_en <= ctr(7);
|
core_en <= ctr(7);
|
ien <= ctr(6);
|
ien <= ctr(6);
|
|
|
-- hookup byte controller block
|
-- hookup byte controller block
|
u1: i2c_master_byte_ctrl port map (
|
byte_ctrl: i2c_master_byte_ctrl port map (
|
clk => wb_clk_i,
|
clk => wb_clk_i,
|
rst => wb_rst_i,
|
rst => wb_rst_i,
|
nReset => rst_i,
|
nReset => rst_i,
|
ena => core_en,
|
ena => core_en,
|
clk_cnt => prer,
|
clk_cnt => prer,
|
Line 261... |
Line 275... |
stop => sto,
|
stop => sto,
|
read => rd,
|
read => rd,
|
write => wr,
|
write => wr,
|
ack_in => ack,
|
ack_in => ack,
|
i2c_busy => i2c_busy,
|
i2c_busy => i2c_busy,
|
|
i2c_al => i2c_al,
|
din => txr,
|
din => txr,
|
cmd_ack => done,
|
cmd_ack => done,
|
ack_out => irxack,
|
ack_out => irxack,
|
dout => rxr,
|
dout => rxr,
|
scl_i => scl_pad_i,
|
scl_i => scl_pad_i,
|
Line 281... |
Line 296... |
begin
|
begin
|
-- generate status register bits
|
-- generate status register bits
|
gen_sr_bits: process (wb_clk_i, rst_i)
|
gen_sr_bits: process (wb_clk_i, rst_i)
|
begin
|
begin
|
if (rst_i = '0') then
|
if (rst_i = '0') then
|
|
al <= '0';
|
rxack <= '0';
|
rxack <= '0';
|
tip <= '0';
|
tip <= '0';
|
irq_flag <= '0';
|
irq_flag <= '0';
|
elsif (wb_clk_i'event and wb_clk_i = '1') then
|
elsif (wb_clk_i'event and wb_clk_i = '1') then
|
if (wb_rst_i = '1') then
|
if (wb_rst_i = '1') then
|
|
al <= '0';
|
rxack <= '0';
|
rxack <= '0';
|
tip <= '0';
|
tip <= '0';
|
irq_flag <= '0';
|
irq_flag <= '0';
|
else
|
else
|
|
al <= i2c_al or (al and not sta);
|
rxack <= irxack;
|
rxack <= irxack;
|
tip <= (rd or wr);
|
tip <= (rd or wr);
|
|
|
-- interrupt request flag is always generated
|
-- interrupt request flag is always generated
|
irq_flag <= (done or irq_flag) and not iack;
|
irq_flag <= (done or i2c_al or irq_flag) and not iack;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process gen_sr_bits;
|
end process gen_sr_bits;
|
|
|
-- generate interrupt request signals
|
-- generate interrupt request signals
|