Line 109... |
Line 109... |
signal twi_sda_in : std_ulogic;
|
signal twi_sda_in : std_ulogic;
|
signal twi_scl_in : std_ulogic;
|
signal twi_scl_in : std_ulogic;
|
signal twi_sda_out : std_ulogic;
|
signal twi_sda_out : std_ulogic;
|
signal twi_scl_out : std_ulogic;
|
signal twi_scl_out : std_ulogic;
|
|
|
-- interrupt generator --
|
|
type irq_t is record
|
|
pending : std_ulogic; -- pending interrupt request
|
|
set : std_ulogic;
|
|
clr : std_ulogic;
|
|
end record;
|
|
signal irq : irq_t;
|
|
|
|
begin
|
begin
|
|
|
-- Access Control -------------------------------------------------------------------------
|
-- Access Control -------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = twi_base_c(hi_abb_c downto lo_abb_c)) else '0';
|
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = twi_base_c(hi_abb_c downto lo_abb_c)) else '0';
|
Line 196... |
Line 188... |
-- input synchronizer & sampler --
|
-- input synchronizer & sampler --
|
twi_sda_in_ff <= twi_sda_in_ff(0) & twi_sda_in;
|
twi_sda_in_ff <= twi_sda_in_ff(0) & twi_sda_in;
|
twi_scl_in_ff <= twi_scl_in_ff(0) & twi_scl_in;
|
twi_scl_in_ff <= twi_scl_in_ff(0) & twi_scl_in;
|
|
|
-- defaults --
|
-- defaults --
|
irq.set <= '0';
|
irq_o <= '0';
|
|
|
-- serial engine --
|
-- serial engine --
|
arbiter(2) <= ctrl(ctrl_en_c); -- still activated?
|
arbiter(2) <= ctrl(ctrl_en_c); -- still activated?
|
case arbiter is
|
case arbiter is
|
|
|
Line 230... |
Line 222... |
--
|
--
|
if (twi_clk_phase(0) = '1') then
|
if (twi_clk_phase(0) = '1') then
|
twi_scl_out <= '1';
|
twi_scl_out <= '1';
|
elsif (twi_clk_phase(3) = '1') then
|
elsif (twi_clk_phase(3) = '1') then
|
twi_scl_out <= '0';
|
twi_scl_out <= '0';
|
irq.set <= '1'; -- Interrupt!
|
irq_o <= '1'; -- Interrupt!
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
end if;
|
end if;
|
|
|
when "110" => -- STOP: generate STOP condition
|
when "110" => -- STOP: generate STOP condition
|
if (twi_clk_phase(0) = '1') then
|
if (twi_clk_phase(0) = '1') then
|
twi_sda_out <= '0';
|
twi_sda_out <= '0';
|
elsif (twi_clk_phase(3) = '1') then
|
elsif (twi_clk_phase(3) = '1') then
|
twi_sda_out <= '1';
|
twi_sda_out <= '1';
|
irq.set <= '1'; -- Interrupt!
|
irq_o <= '1'; -- Interrupt!
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
end if;
|
end if;
|
--
|
--
|
if (twi_clk_phase(0) = '1') then
|
if (twi_clk_phase(0) = '1') then
|
twi_scl_out <= '0';
|
twi_scl_out <= '0';
|
Line 262... |
Line 254... |
rtx_sreg <= rtx_sreg(7 downto 0) & twi_sda_in_ff(twi_sda_in_ff'left); -- sample and shift left
|
rtx_sreg <= rtx_sreg(7 downto 0) & twi_sda_in_ff(twi_sda_in_ff'left); -- sample and shift left
|
twi_scl_out <= '0';
|
twi_scl_out <= '0';
|
end if;
|
end if;
|
--
|
--
|
if (bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
|
if (bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
|
irq.set <= '1'; -- Interrupt!
|
irq_o <= '1'; -- Interrupt!
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
arbiter(1 downto 0) <= "00"; -- go back to IDLE
|
end if;
|
end if;
|
|
|
when others => -- "0--" OFFLINE: TWI deactivated
|
when others => -- "0--" OFFLINE: TWI deactivated
|
twi_sda_out <= '1';
|
twi_sda_out <= '1';
|
Line 293... |
Line 285... |
-- read-back --
|
-- read-back --
|
twi_sda_in <= std_ulogic(twi_sda_io);
|
twi_sda_in <= std_ulogic(twi_sda_io);
|
twi_scl_in <= std_ulogic(twi_scl_io);
|
twi_scl_in <= std_ulogic(twi_scl_io);
|
|
|
|
|
-- Interrupt Generator --------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
irq_generator: process(clk_i)
|
|
begin
|
|
if rising_edge(clk_i) then
|
|
if (ctrl(ctrl_en_c) = '0') then
|
|
irq.pending <= '0';
|
|
else
|
|
if (irq.set = '1') then
|
|
irq.pending <= '1';
|
|
elsif (irq.clr = '1') then
|
|
irq.pending <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process irq_generator;
|
|
|
|
-- IRQ request to CPU --
|
|
irq_o <= irq.pending;
|
|
|
|
-- IRQ acknowledge --
|
|
irq.clr <= '1' when ((rden = '1') and (addr = twi_rtx_addr_c)) or (wren = '1') else '0'; -- read data register OR write data/control register
|
|
|
|
|
|
end neorv32_twi_rtl;
|
end neorv32_twi_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|