Compare commits
11 Commits
1-1_SIM_MU
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
08e9b65979 | |
|
|
58bb42cd13 | |
|
|
7439984c8c | |
|
|
b1782ac316 | |
|
|
611076ca6d | |
|
|
aed7bf198a | |
|
|
ef784c054e | |
|
|
5cc12bdf6d | |
|
|
49a8fd7224 | |
|
|
d82a0ab464 | |
|
|
86c7da5075 |
|
|
@ -0,0 +1 @@
|
||||||
|
*.bak
|
||||||
|
|
@ -0,0 +1,253 @@
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- FileName: i2c_master.vhd
|
||||||
|
-- Dependencies: none
|
||||||
|
-- Design Software: Quartus II 64-bit Version 13.1 Build 162 SJ Full Version
|
||||||
|
--
|
||||||
|
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
||||||
|
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
||||||
|
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||||
|
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
||||||
|
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
||||||
|
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
||||||
|
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
||||||
|
--
|
||||||
|
-- Version History
|
||||||
|
-- Version 1.0 11/01/2012 Scott Larson
|
||||||
|
-- Initial Public Release
|
||||||
|
-- Version 2.0 06/20/2014 Scott Larson
|
||||||
|
-- Added ability to interface with different slaves in the same transaction
|
||||||
|
-- Corrected ack_error bug where ack_error went 'Z' instead of '1' on error
|
||||||
|
-- Corrected timing of when ack_error signal clears
|
||||||
|
-- Version 2.1 10/21/2014 Scott Larson
|
||||||
|
-- Replaced gated clock with clock enable
|
||||||
|
-- Adjusted timing of SCL during start and stop conditions
|
||||||
|
-- Version 2.2 02/05/2015 Scott Larson
|
||||||
|
-- Corrected small SDA glitch introduced in version 2.1
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY ieee;
|
||||||
|
USE ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
--USE ieee.std_logic_unsigned.all;
|
||||||
|
|
||||||
|
ENTITY i2c_master IS
|
||||||
|
GENERIC(
|
||||||
|
input_clk : INTEGER := 50_000_000; --input clock speed from user logic in Hz
|
||||||
|
bus_clk : INTEGER := 400_000); --speed the i2c bus (scl) will run at in Hz
|
||||||
|
PORT(
|
||||||
|
clk : IN STD_LOGIC; --system clock
|
||||||
|
reset_n : IN STD_LOGIC; --active low reset
|
||||||
|
ena : IN STD_LOGIC; --latch in command
|
||||||
|
addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave
|
||||||
|
rw : IN STD_LOGIC; --'0' is write, '1' is read
|
||||||
|
data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave
|
||||||
|
busy : OUT STD_LOGIC; --indicates transaction in progress
|
||||||
|
data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data read from slave
|
||||||
|
ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave
|
||||||
|
sda : INOUT STD_LOGIC; --serial data output of i2c bus
|
||||||
|
scl : INOUT STD_LOGIC; --serial clock output of i2c bus
|
||||||
|
scl_invert: IN STD_LOGIC --true if need to invert output SCL signal
|
||||||
|
);
|
||||||
|
END i2c_master;
|
||||||
|
|
||||||
|
ARCHITECTURE logic OF i2c_master IS
|
||||||
|
CONSTANT divider : INTEGER := (input_clk/bus_clk)/4; --number of clocks in 1/4 cycle of scl
|
||||||
|
TYPE machine IS(ready, start, command, slv_ack1, wr, rd, slv_ack2, mstr_ack, stop); --needed states
|
||||||
|
SIGNAL state : machine; --state machine
|
||||||
|
SIGNAL data_clk : STD_LOGIC; --data clock for sda
|
||||||
|
SIGNAL data_clk_prev : STD_LOGIC; --data clock during previous system clock
|
||||||
|
SIGNAL scl_clk : STD_LOGIC; --constantly running internal scl
|
||||||
|
SIGNAL scl_ena : STD_LOGIC := '0'; --enables internal scl to output
|
||||||
|
SIGNAL sda_int : STD_LOGIC := '1'; --internal sda
|
||||||
|
SIGNAL sda_ena_n : STD_LOGIC; --enables internal sda to output
|
||||||
|
SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write
|
||||||
|
SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave
|
||||||
|
SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave
|
||||||
|
SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction
|
||||||
|
SIGNAL stretch : STD_LOGIC := '0'; --identifies if slave is stretching scl
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
--generate the timing for the bus clock (scl_clk) and the data clock (data_clk)
|
||||||
|
PROCESS(clk, reset_n)
|
||||||
|
VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock generation
|
||||||
|
BEGIN
|
||||||
|
IF(reset_n = '0') THEN --reset asserted
|
||||||
|
stretch <= '0';
|
||||||
|
count := 0;
|
||||||
|
ELSIF(clk'EVENT AND clk = '1') THEN
|
||||||
|
data_clk_prev <= data_clk; --store previous value of data clock
|
||||||
|
IF(count = divider*4-1) THEN --end of timing cycle
|
||||||
|
count := 0; --reset timer
|
||||||
|
ELSIF(stretch = '0') THEN --clock stretching from slave not detected
|
||||||
|
count := count + 1; --continue clock generation timing
|
||||||
|
END IF;
|
||||||
|
CASE count IS
|
||||||
|
WHEN 0 TO divider-1 => --first 1/4 cycle of clocking
|
||||||
|
scl_clk <= '0';
|
||||||
|
data_clk <= '0';
|
||||||
|
WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking
|
||||||
|
scl_clk <= '0';
|
||||||
|
data_clk <= '1';
|
||||||
|
WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking
|
||||||
|
scl_clk <= '1'; --release scl
|
||||||
|
IF(scl = '0') THEN --detect if slave is stretching clock
|
||||||
|
stretch <= '1';
|
||||||
|
ELSE
|
||||||
|
stretch <= '0';
|
||||||
|
END IF;
|
||||||
|
data_clk <= '1';
|
||||||
|
WHEN OTHERS => --last 1/4 cycle of clocking
|
||||||
|
scl_clk <= '1';
|
||||||
|
data_clk <= '0';
|
||||||
|
END CASE;
|
||||||
|
END IF;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
--state machine and writing to sda during scl low (data_clk rising edge)
|
||||||
|
PROCESS(clk, reset_n)
|
||||||
|
BEGIN
|
||||||
|
IF(reset_n = '0') THEN --reset asserted
|
||||||
|
state <= ready; --return to initial state
|
||||||
|
busy <= '1'; --indicate not available
|
||||||
|
scl_ena <= '0'; --sets scl high impedance
|
||||||
|
sda_int <= '1'; --sets sda high impedance
|
||||||
|
ack_error <= '0'; --clear acknowledge error flag
|
||||||
|
bit_cnt <= 7; --restarts data bit counter
|
||||||
|
data_rd <= "00000000"; --clear data read port
|
||||||
|
ELSIF(clk'EVENT AND clk = '1') THEN
|
||||||
|
IF(data_clk = '1' AND data_clk_prev = '0') THEN --data clock rising edge
|
||||||
|
CASE state IS
|
||||||
|
WHEN ready => --idle state
|
||||||
|
IF(ena = '1') THEN --transaction requested
|
||||||
|
busy <= '1'; --flag busy
|
||||||
|
addr_rw <= addr & rw; --collect requested slave address and command
|
||||||
|
data_tx <= data_wr; --collect requested data to write
|
||||||
|
state <= start; --go to start bit
|
||||||
|
ELSE --remain idle
|
||||||
|
busy <= '0'; --unflag busy
|
||||||
|
state <= ready; --remain idle
|
||||||
|
END IF;
|
||||||
|
WHEN start => --start bit of transaction
|
||||||
|
busy <= '1'; --resume busy if continuous mode
|
||||||
|
sda_int <= addr_rw(bit_cnt); --set first address bit to bus
|
||||||
|
state <= command; --go to command
|
||||||
|
WHEN command => --address and command byte of transaction
|
||||||
|
IF(bit_cnt = 0) THEN --command transmit finished
|
||||||
|
sda_int <= '1'; --release sda for slave acknowledge
|
||||||
|
bit_cnt <= 7; --reset bit counter for "byte" states
|
||||||
|
state <= slv_ack1; --go to slave acknowledge (command)
|
||||||
|
ELSE --next clock cycle of command state
|
||||||
|
bit_cnt <= bit_cnt - 1; --keep track of transaction bits
|
||||||
|
sda_int <= addr_rw(bit_cnt-1); --write address/command bit to bus
|
||||||
|
state <= command; --continue with command
|
||||||
|
END IF;
|
||||||
|
WHEN slv_ack1 => --slave acknowledge bit (command)
|
||||||
|
IF(addr_rw(0) = '0') THEN --write command
|
||||||
|
sda_int <= data_tx(bit_cnt); --write first bit of data
|
||||||
|
state <= wr; --go to write byte
|
||||||
|
ELSE --read command
|
||||||
|
sda_int <= '1'; --release sda from incoming data
|
||||||
|
state <= rd; --go to read byte
|
||||||
|
END IF;
|
||||||
|
WHEN wr => --write byte of transaction
|
||||||
|
busy <= '1'; --resume busy if continuous mode
|
||||||
|
IF(bit_cnt = 0) THEN --write byte transmit finished
|
||||||
|
sda_int <= '1'; --release sda for slave acknowledge
|
||||||
|
bit_cnt <= 7; --reset bit counter for "byte" states
|
||||||
|
state <= slv_ack2; --go to slave acknowledge (write)
|
||||||
|
ELSE --next clock cycle of write state
|
||||||
|
bit_cnt <= bit_cnt - 1; --keep track of transaction bits
|
||||||
|
sda_int <= data_tx(bit_cnt-1); --write next bit to bus
|
||||||
|
state <= wr; --continue writing
|
||||||
|
END IF;
|
||||||
|
WHEN rd => --read byte of transaction
|
||||||
|
busy <= '1'; --resume busy if continuous mode
|
||||||
|
IF(bit_cnt = 0) THEN --read byte receive finished
|
||||||
|
IF(ena = '1' AND addr_rw = addr & rw) THEN --continuing with another read at same address
|
||||||
|
sda_int <= '0'; --acknowledge the byte has been received
|
||||||
|
ELSE --stopping or continuing with a write
|
||||||
|
sda_int <= '1'; --send a no-acknowledge (before stop or repeated start)
|
||||||
|
END IF;
|
||||||
|
bit_cnt <= 7; --reset bit counter for "byte" states
|
||||||
|
data_rd <= data_rx; --output received data
|
||||||
|
state <= mstr_ack; --go to master acknowledge
|
||||||
|
ELSE --next clock cycle of read state
|
||||||
|
bit_cnt <= bit_cnt - 1; --keep track of transaction bits
|
||||||
|
state <= rd; --continue reading
|
||||||
|
END IF;
|
||||||
|
WHEN slv_ack2 => --slave acknowledge bit (write)
|
||||||
|
IF(ena = '1') THEN --continue transaction
|
||||||
|
busy <= '0'; --continue is accepted
|
||||||
|
addr_rw <= addr & rw; --collect requested slave address and command
|
||||||
|
data_tx <= data_wr; --collect requested data to write
|
||||||
|
IF(addr_rw = addr & rw) THEN --continue transaction with another write
|
||||||
|
sda_int <= data_wr(bit_cnt); --write first bit of data
|
||||||
|
state <= wr; --go to write byte
|
||||||
|
ELSE --continue transaction with a read or new slave
|
||||||
|
state <= start; --go to repeated start
|
||||||
|
END IF;
|
||||||
|
ELSE --complete transaction
|
||||||
|
state <= stop; --go to stop bit
|
||||||
|
END IF;
|
||||||
|
WHEN mstr_ack => --master acknowledge bit after a read
|
||||||
|
IF(ena = '1') THEN --continue transaction
|
||||||
|
busy <= '0'; --continue is accepted and data received is available on bus
|
||||||
|
addr_rw <= addr & rw; --collect requested slave address and command
|
||||||
|
data_tx <= data_wr; --collect requested data to write
|
||||||
|
IF(addr_rw = addr & rw) THEN --continue transaction with another read
|
||||||
|
sda_int <= '1'; --release sda from incoming data
|
||||||
|
state <= rd; --go to read byte
|
||||||
|
ELSE --continue transaction with a write or new slave
|
||||||
|
state <= start; --repeated start
|
||||||
|
END IF;
|
||||||
|
ELSE --complete transaction
|
||||||
|
state <= stop; --go to stop bit
|
||||||
|
END IF;
|
||||||
|
WHEN stop => --stop bit of transaction
|
||||||
|
busy <= '0'; --unflag busy
|
||||||
|
state <= ready; --go to idle state
|
||||||
|
END CASE;
|
||||||
|
ELSIF(data_clk = '0' AND data_clk_prev = '1') THEN --data clock falling edge
|
||||||
|
CASE state IS
|
||||||
|
WHEN start =>
|
||||||
|
IF(scl_ena = '0') THEN --starting new transaction
|
||||||
|
scl_ena <= '1'; --enable scl output
|
||||||
|
ack_error <= '0'; --reset acknowledge error output
|
||||||
|
END IF;
|
||||||
|
WHEN slv_ack1 => --receiving slave acknowledge (command)
|
||||||
|
IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
|
||||||
|
ack_error <= '1'; --set error output if no-acknowledge
|
||||||
|
END IF;
|
||||||
|
WHEN rd => --receiving slave data
|
||||||
|
data_rx(bit_cnt) <= sda; --receive current slave data bit
|
||||||
|
WHEN slv_ack2 => --receiving slave acknowledge (write)
|
||||||
|
IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
|
||||||
|
ack_error <= '1'; --set error output if no-acknowledge
|
||||||
|
END IF;
|
||||||
|
WHEN stop =>
|
||||||
|
scl_ena <= '0'; --disable scl
|
||||||
|
WHEN OTHERS =>
|
||||||
|
NULL;
|
||||||
|
END CASE;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
--set sda output
|
||||||
|
WITH state SELECT
|
||||||
|
sda_ena_n <= data_clk_prev WHEN start, --generate start condition
|
||||||
|
NOT data_clk_prev WHEN stop, --generate stop condition
|
||||||
|
sda_int WHEN OTHERS; --set to internal sda signal
|
||||||
|
|
||||||
|
--set scl and sda outputs
|
||||||
|
--scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0') ELSE 'Z';
|
||||||
|
scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0' AND scl_invert = '0') ELSE
|
||||||
|
'1' WHEN (scl_ena = '1' AND scl_clk = '0' AND scl_invert = '1') ELSE
|
||||||
|
'Z';
|
||||||
|
sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z';
|
||||||
|
|
||||||
|
END logic;
|
||||||
|
|
@ -0,0 +1,301 @@
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- File : I2C_slave.vhd
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Author : Peter Samarin <peter.samarin@gmail.com>
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Copyright (c) 2016 Peter Samarin
|
||||||
|
------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
------------------------------------------------------------
|
||||||
|
entity i2c_slave is
|
||||||
|
generic (
|
||||||
|
SLAVE_ADDR : std_logic_vector(6 downto 0));
|
||||||
|
port (
|
||||||
|
scl : inout std_logic;
|
||||||
|
sda : inout std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
rst : in std_logic;
|
||||||
|
-- User interface
|
||||||
|
read_req : out std_logic;
|
||||||
|
data_to_master : in std_logic_vector(7 downto 0);
|
||||||
|
data_valid : out std_logic;
|
||||||
|
data_from_master : out std_logic_vector(7 downto 0));
|
||||||
|
end entity i2c_slave;
|
||||||
|
------------------------------------------------------------
|
||||||
|
architecture arch of i2c_slave is
|
||||||
|
-- this assumes that system's clock is much faster than SCL
|
||||||
|
constant DEBOUNCING_WAIT_CYCLES : integer := 4;
|
||||||
|
|
||||||
|
type state_t is (idle, get_address_and_cmd,
|
||||||
|
answer_ack_start, write,
|
||||||
|
read, read_ack_start,
|
||||||
|
read_ack_got_rising, read_stop);
|
||||||
|
-- I2C state management
|
||||||
|
signal state_reg : state_t := idle;
|
||||||
|
signal cmd_reg : std_logic := '0';
|
||||||
|
signal bits_processed_reg : integer range 0 to 8 := 0;
|
||||||
|
signal continue_reg : std_logic := '0';
|
||||||
|
|
||||||
|
signal scl_reg : std_logic := '1';
|
||||||
|
signal sda_reg : std_logic := '1';
|
||||||
|
signal scl_debounced : std_logic := '1';
|
||||||
|
signal sda_debounced : std_logic := '1';
|
||||||
|
|
||||||
|
|
||||||
|
-- Helpers to figure out next state
|
||||||
|
signal start_reg : std_logic := '0';
|
||||||
|
signal stop_reg : std_logic := '0';
|
||||||
|
signal scl_rising_reg : std_logic := '0';
|
||||||
|
signal scl_falling_reg : std_logic := '0';
|
||||||
|
|
||||||
|
-- Address and data received from master
|
||||||
|
signal addr_reg : std_logic_vector(6 downto 0) := (others => '0');
|
||||||
|
signal data_reg : std_logic_vector(6 downto 0) := (others => '0');
|
||||||
|
signal data_from_master_reg : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
signal scl_prev_reg : std_logic := '1';
|
||||||
|
-- Slave writes on scl
|
||||||
|
signal scl_wen_reg : std_logic := '0';
|
||||||
|
signal scl_o_reg : std_logic := '0';
|
||||||
|
signal sda_prev_reg : std_logic := '1';
|
||||||
|
-- Slave writes on sda
|
||||||
|
signal sda_wen_reg : std_logic := '0';
|
||||||
|
signal sda_o_reg : std_logic := '0';
|
||||||
|
|
||||||
|
-- User interface
|
||||||
|
signal data_valid_reg : std_logic := '0';
|
||||||
|
signal read_req_reg : std_logic := '0';
|
||||||
|
signal data_to_master_reg : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- debounce SCL and SDA
|
||||||
|
SCL_debounce : entity work.debounce
|
||||||
|
generic map (
|
||||||
|
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES)
|
||||||
|
port map (
|
||||||
|
clk => clk,
|
||||||
|
signal_in => scl_reg,
|
||||||
|
signal_out => scl_debounced);
|
||||||
|
|
||||||
|
-- it might not make sense to debounce SDA, since master
|
||||||
|
-- and slave can both write to it...
|
||||||
|
SDA_debounce : entity work.debounce
|
||||||
|
generic map (
|
||||||
|
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES)
|
||||||
|
port map (
|
||||||
|
clk => clk,
|
||||||
|
signal_in => sda_reg,
|
||||||
|
signal_out => sda_debounced);
|
||||||
|
|
||||||
|
process (clk) is
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
-- save SCL in registers that are used for debouncing
|
||||||
|
scl_reg <= scl;
|
||||||
|
sda_reg <= sda;
|
||||||
|
|
||||||
|
-- Delay debounced SCL and SDA by 1 clock cycle
|
||||||
|
scl_prev_reg <= scl_debounced;
|
||||||
|
sda_prev_reg <= sda_debounced;
|
||||||
|
-- Detect rising and falling SCL
|
||||||
|
scl_rising_reg <= '0';
|
||||||
|
if scl_prev_reg = '0' and scl_debounced = '1' then
|
||||||
|
scl_rising_reg <= '1';
|
||||||
|
end if;
|
||||||
|
scl_falling_reg <= '0';
|
||||||
|
if scl_prev_reg = '1' and scl_debounced = '0' then
|
||||||
|
scl_falling_reg <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Detect I2C START condition
|
||||||
|
start_reg <= '0';
|
||||||
|
stop_reg <= '0';
|
||||||
|
if scl_debounced = '1' and scl_prev_reg = '1' and
|
||||||
|
sda_prev_reg = '1' and sda_debounced = '0' then
|
||||||
|
start_reg <= '1';
|
||||||
|
stop_reg <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Detect I2C STOP condition
|
||||||
|
if scl_prev_reg = '1' and scl_debounced = '1' and
|
||||||
|
sda_prev_reg = '0' and sda_debounced = '1' then
|
||||||
|
start_reg <= '0';
|
||||||
|
stop_reg <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
----------------------------------------------------------
|
||||||
|
-- I2C state machine
|
||||||
|
----------------------------------------------------------
|
||||||
|
process (clk) is
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
-- Default assignments
|
||||||
|
sda_o_reg <= '0';
|
||||||
|
sda_wen_reg <= '0';
|
||||||
|
-- User interface
|
||||||
|
data_valid_reg <= '0';
|
||||||
|
read_req_reg <= '0';
|
||||||
|
|
||||||
|
case state_reg is
|
||||||
|
|
||||||
|
when idle =>
|
||||||
|
if start_reg = '1' then
|
||||||
|
state_reg <= get_address_and_cmd;
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when get_address_and_cmd =>
|
||||||
|
if scl_rising_reg = '1' then
|
||||||
|
if bits_processed_reg < 7 then
|
||||||
|
bits_processed_reg <= bits_processed_reg + 1;
|
||||||
|
addr_reg(6-bits_processed_reg) <= sda_debounced;
|
||||||
|
elsif bits_processed_reg = 7 then
|
||||||
|
bits_processed_reg <= bits_processed_reg + 1;
|
||||||
|
cmd_reg <= sda_debounced;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if bits_processed_reg = 8 and scl_falling_reg = '1' then
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
if addr_reg = SLAVE_ADDR then -- check req address
|
||||||
|
state_reg <= answer_ack_start;
|
||||||
|
if cmd_reg = '1' then -- issue read request
|
||||||
|
read_req_reg <= '1';
|
||||||
|
data_to_master_reg <= data_to_master;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
assert false
|
||||||
|
report ("I2C: target/slave address mismatch (data is being sent to another slave).")
|
||||||
|
severity note;
|
||||||
|
state_reg <= idle;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
-- I2C acknowledge to master
|
||||||
|
----------------------------------------------------
|
||||||
|
when answer_ack_start =>
|
||||||
|
sda_wen_reg <= '1';
|
||||||
|
sda_o_reg <= '0';
|
||||||
|
if scl_falling_reg = '1' then
|
||||||
|
if cmd_reg = '0' then
|
||||||
|
state_reg <= write;
|
||||||
|
else
|
||||||
|
state_reg <= read;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
-- WRITE
|
||||||
|
----------------------------------------------------
|
||||||
|
when write =>
|
||||||
|
if scl_rising_reg = '1' then
|
||||||
|
bits_processed_reg <= bits_processed_reg + 1;
|
||||||
|
if bits_processed_reg < 7 then
|
||||||
|
data_reg(6-bits_processed_reg) <= sda_debounced;
|
||||||
|
else
|
||||||
|
data_from_master_reg <= data_reg & sda_debounced;
|
||||||
|
data_valid_reg <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if scl_falling_reg = '1' and bits_processed_reg = 8 then
|
||||||
|
state_reg <= answer_ack_start;
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
-- READ: send data to master
|
||||||
|
----------------------------------------------------
|
||||||
|
when read =>
|
||||||
|
sda_wen_reg <= '1';
|
||||||
|
sda_o_reg <= data_to_master_reg(7-bits_processed_reg);
|
||||||
|
if scl_falling_reg = '1' then
|
||||||
|
if bits_processed_reg < 7 then
|
||||||
|
bits_processed_reg <= bits_processed_reg + 1;
|
||||||
|
elsif bits_processed_reg = 7 then
|
||||||
|
state_reg <= read_ack_start;
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
-- I2C read master acknowledge
|
||||||
|
----------------------------------------------------
|
||||||
|
when read_ack_start =>
|
||||||
|
if scl_rising_reg = '1' then
|
||||||
|
state_reg <= read_ack_got_rising;
|
||||||
|
if sda_debounced = '1' then -- nack = stop read
|
||||||
|
continue_reg <= '0';
|
||||||
|
else -- ack = continue read
|
||||||
|
continue_reg <= '1';
|
||||||
|
read_req_reg <= '1'; -- request reg byte
|
||||||
|
data_to_master_reg <= data_to_master;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when read_ack_got_rising =>
|
||||||
|
if scl_falling_reg = '1' then
|
||||||
|
if continue_reg = '1' then
|
||||||
|
if cmd_reg = '0' then
|
||||||
|
state_reg <= write;
|
||||||
|
else
|
||||||
|
state_reg <= read;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
state_reg <= read_stop;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Wait for START or STOP to get out of this state
|
||||||
|
when read_stop =>
|
||||||
|
null;
|
||||||
|
|
||||||
|
-- Wait for START or STOP to get out of this state
|
||||||
|
when others =>
|
||||||
|
assert false
|
||||||
|
report ("I2C: error: ended in an impossible state.")
|
||||||
|
severity error;
|
||||||
|
state_reg <= idle;
|
||||||
|
end case;
|
||||||
|
|
||||||
|
--------------------------------------------------------
|
||||||
|
-- Reset counter and state on start/stop
|
||||||
|
--------------------------------------------------------
|
||||||
|
if start_reg = '1' then
|
||||||
|
state_reg <= get_address_and_cmd;
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if stop_reg = '1' then
|
||||||
|
state_reg <= idle;
|
||||||
|
bits_processed_reg <= 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if rst = '1' then
|
||||||
|
state_reg <= idle;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
----------------------------------------------------------
|
||||||
|
-- I2C interface
|
||||||
|
----------------------------------------------------------
|
||||||
|
sda <= sda_o_reg when sda_wen_reg = '1' else
|
||||||
|
'Z';
|
||||||
|
scl <= scl_o_reg when scl_wen_reg = '1' else
|
||||||
|
'Z';
|
||||||
|
----------------------------------------------------------
|
||||||
|
-- User interface
|
||||||
|
----------------------------------------------------------
|
||||||
|
-- Master writes
|
||||||
|
data_valid <= data_valid_reg;
|
||||||
|
data_from_master <= data_from_master_reg;
|
||||||
|
-- Master reads
|
||||||
|
read_req <= read_req_reg;
|
||||||
|
end architecture arch;
|
||||||
|
|
@ -0,0 +1,358 @@
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use work.sim_switcher_pkg.all;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
entity sim_mux is
|
||||||
|
port (
|
||||||
|
reg_sim_modemnum : arr_modnum_t(0 to 7);
|
||||||
|
sim_rst_o : out std_logic_vector(7 downto 0);
|
||||||
|
mod_simrst_i : in std_logic_vector(7 downto 0);
|
||||||
|
sim_clk_o : out std_logic_vector(7 downto 0);
|
||||||
|
mod_clk_i : in std_logic_vector(7 downto 0);
|
||||||
|
mod_detect_o : out std_logic_vector(3 downto 0);
|
||||||
|
sim_detect_i : in std_logic_vector(7 downto 0);
|
||||||
|
sw_mod_data_i : out std_logic_vector(7 downto 0); -- For switched tri-state buffer there are input and output part of
|
||||||
|
mod_data_i : in std_logic_vector(7 downto 0); -- the lines which are switched transparently, thus ports
|
||||||
|
mod_data_o : out std_logic_vector(7 downto 0); -- sw_mod_data_i is actual output and sw_mod_data_o is
|
||||||
|
sw_mod_data_o : in std_logic_vector(7 downto 0) -- actual input. Please, don't be confused.
|
||||||
|
);
|
||||||
|
end entity sim_mux;
|
||||||
|
------------------------------------------------------------
|
||||||
|
architecture arch of sim_mux is
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Switch lines of SIM according to connected MODEM
|
||||||
|
sim_rst_o(0) <= mod_simrst_i(0) when reg_sim_modemnum(0) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(0) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(0) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(0) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(0) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(0) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(0) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(0) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(1) <= mod_simrst_i(0) when reg_sim_modemnum(1) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(1) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(1) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(1) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(1) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(1) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(1) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(1) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(2) <= mod_simrst_i(0) when reg_sim_modemnum(2) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(2) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(2) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(2) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(2) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(2) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(2) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(2) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(3) <= mod_simrst_i(0) when reg_sim_modemnum(3) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(3) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(3) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(3) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(3) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(3) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(3) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(3) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(4) <= mod_simrst_i(0) when reg_sim_modemnum(4) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(4) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(4) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(4) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(4) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(4) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(4) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(4) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(5) <= mod_simrst_i(0) when reg_sim_modemnum(5) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(5) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(5) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(5) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(5) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(5) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(5) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(5) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(6) <= mod_simrst_i(0) when reg_sim_modemnum(6) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(6) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(6) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(6) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(6) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(6) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(6) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(6) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_rst_o(7) <= mod_simrst_i(0) when reg_sim_modemnum(7) = 0
|
||||||
|
else mod_simrst_i(1) when reg_sim_modemnum(7) = 1
|
||||||
|
else mod_simrst_i(2) when reg_sim_modemnum(7) = 2
|
||||||
|
else mod_simrst_i(3) when reg_sim_modemnum(7) = 3
|
||||||
|
else mod_simrst_i(4) when reg_sim_modemnum(7) = 4
|
||||||
|
else mod_simrst_i(5) when reg_sim_modemnum(7) = 5
|
||||||
|
else mod_simrst_i(6) when reg_sim_modemnum(7) = 6
|
||||||
|
else mod_simrst_i(7) when reg_sim_modemnum(7) = 7
|
||||||
|
else 'Z';
|
||||||
|
|
||||||
|
-- Switch CLK line of SIM according to connected MODEM
|
||||||
|
sim_clk_o(0) <= mod_clk_i(0) when reg_sim_modemnum(0) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(0) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(0) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(0) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(0) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(0) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(0) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(0) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(1) <= mod_clk_i(0) when reg_sim_modemnum(1) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(1) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(1) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(1) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(1) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(1) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(1) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(1) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(2) <= mod_clk_i(0) when reg_sim_modemnum(2) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(2) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(2) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(2) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(2) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(2) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(2) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(2) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(3) <= mod_clk_i(0) when reg_sim_modemnum(3) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(3) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(3) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(3) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(3) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(3) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(3) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(3) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(4) <= mod_clk_i(0) when reg_sim_modemnum(4) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(4) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(4) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(4) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(4) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(4) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(4) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(4) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(5) <= mod_clk_i(0) when reg_sim_modemnum(5) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(5) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(5) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(5) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(5) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(5) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(5) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(5) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(6) <= mod_clk_i(0) when reg_sim_modemnum(6) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(6) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(6) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(6) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(6) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(6) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(6) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(6) = 7
|
||||||
|
else 'Z';
|
||||||
|
sim_clk_o(7) <= mod_clk_i(0) when reg_sim_modemnum(7) = 0
|
||||||
|
else mod_clk_i(1) when reg_sim_modemnum(7) = 1
|
||||||
|
else mod_clk_i(2) when reg_sim_modemnum(7) = 2
|
||||||
|
else mod_clk_i(3) when reg_sim_modemnum(7) = 3
|
||||||
|
else mod_clk_i(4) when reg_sim_modemnum(7) = 4
|
||||||
|
else mod_clk_i(5) when reg_sim_modemnum(7) = 5
|
||||||
|
else mod_clk_i(6) when reg_sim_modemnum(7) = 6
|
||||||
|
else mod_clk_i(7) when reg_sim_modemnum(7) = 7
|
||||||
|
else 'Z';
|
||||||
|
|
||||||
|
-- Switch SIM DETECT line of SIM according to connected MODEM,
|
||||||
|
mod_detect_o(0) <= sim_detect_i(0) when reg_sim_modemnum(0) = 0
|
||||||
|
else sim_detect_i(1) when reg_sim_modemnum(1) = 0
|
||||||
|
else sim_detect_i(2) when reg_sim_modemnum(2) = 0
|
||||||
|
else sim_detect_i(3) when reg_sim_modemnum(3) = 0
|
||||||
|
else sim_detect_i(4) when reg_sim_modemnum(4) = 0
|
||||||
|
else sim_detect_i(5) when reg_sim_modemnum(5) = 0
|
||||||
|
else sim_detect_i(6) when reg_sim_modemnum(6) = 0
|
||||||
|
else sim_detect_i(7) when reg_sim_modemnum(7) = 0
|
||||||
|
else 'Z';
|
||||||
|
mod_detect_o(1) <= sim_detect_i(0) when reg_sim_modemnum(0) = 1
|
||||||
|
else sim_detect_i(1) when reg_sim_modemnum(1) = 1
|
||||||
|
else sim_detect_i(2) when reg_sim_modemnum(2) = 1
|
||||||
|
else sim_detect_i(3) when reg_sim_modemnum(3) = 1
|
||||||
|
else sim_detect_i(4) when reg_sim_modemnum(4) = 1
|
||||||
|
else sim_detect_i(5) when reg_sim_modemnum(5) = 1
|
||||||
|
else sim_detect_i(6) when reg_sim_modemnum(6) = 1
|
||||||
|
else sim_detect_i(7) when reg_sim_modemnum(7) = 1
|
||||||
|
else 'Z';
|
||||||
|
mod_detect_o(2) <= sim_detect_i(0) when reg_sim_modemnum(0) = 2
|
||||||
|
else sim_detect_i(1) when reg_sim_modemnum(1) = 2
|
||||||
|
else sim_detect_i(2) when reg_sim_modemnum(2) = 2
|
||||||
|
else sim_detect_i(3) when reg_sim_modemnum(3) = 2
|
||||||
|
else sim_detect_i(4) when reg_sim_modemnum(4) = 2
|
||||||
|
else sim_detect_i(5) when reg_sim_modemnum(5) = 2
|
||||||
|
else sim_detect_i(6) when reg_sim_modemnum(6) = 2
|
||||||
|
else sim_detect_i(7) when reg_sim_modemnum(7) = 2
|
||||||
|
else 'Z';
|
||||||
|
mod_detect_o(3) <= sim_detect_i(0) when reg_sim_modemnum(0) = 3
|
||||||
|
else sim_detect_i(1) when reg_sim_modemnum(1) = 3
|
||||||
|
else sim_detect_i(2) when reg_sim_modemnum(2) = 3
|
||||||
|
else sim_detect_i(3) when reg_sim_modemnum(3) = 3
|
||||||
|
else sim_detect_i(4) when reg_sim_modemnum(4) = 3
|
||||||
|
else sim_detect_i(5) when reg_sim_modemnum(5) = 3
|
||||||
|
else sim_detect_i(6) when reg_sim_modemnum(6) = 3
|
||||||
|
else sim_detect_i(7) when reg_sim_modemnum(7) = 3
|
||||||
|
else 'Z';
|
||||||
|
|
||||||
|
|
||||||
|
sw_mod_data_i(0) <= mod_data_i(0) when reg_sim_modemnum(0) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(0) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(0) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(0) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(0) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(0) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(0) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(0) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(1) <= mod_data_i(0) when reg_sim_modemnum(1) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(1) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(1) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(1) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(1) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(1) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(1) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(1) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(2) <= mod_data_i(0) when reg_sim_modemnum(2) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(2) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(2) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(2) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(2) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(2) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(2) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(2) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(3) <= mod_data_i(0) when reg_sim_modemnum(3) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(3) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(3) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(3) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(3) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(3) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(3) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(3) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(4) <= mod_data_i(0) when reg_sim_modemnum(4) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(4) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(4) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(4) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(4) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(4) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(4) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(4) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(5) <= mod_data_i(0) when reg_sim_modemnum(5) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(5) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(5) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(5) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(5) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(5) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(5) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(5) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(6) <= mod_data_i(0) when reg_sim_modemnum(6) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(6) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(6) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(6) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(6) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(6) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(6) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(6) = 7
|
||||||
|
else '1';
|
||||||
|
sw_mod_data_i(7) <= mod_data_i(0) when reg_sim_modemnum(7) = 0
|
||||||
|
else mod_data_i(1) when reg_sim_modemnum(7) = 1
|
||||||
|
else mod_data_i(2) when reg_sim_modemnum(7) = 2
|
||||||
|
else mod_data_i(3) when reg_sim_modemnum(7) = 3
|
||||||
|
else mod_data_i(4) when reg_sim_modemnum(7) = 4
|
||||||
|
else mod_data_i(5) when reg_sim_modemnum(7) = 5
|
||||||
|
else mod_data_i(6) when reg_sim_modemnum(7) = 6
|
||||||
|
else mod_data_i(7) when reg_sim_modemnum(7) = 7
|
||||||
|
else '1';
|
||||||
|
|
||||||
|
mod_data_o(0) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 0
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 0
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 0
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 0
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 0
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 0
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 0
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 0
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(1) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 1
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 1
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 1
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 1
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 1
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 1
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 1
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 1
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(2) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 2
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 2
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 2
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 2
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 2
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 2
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 2
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 2
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(3) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 3
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 3
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 3
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 3
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 3
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 3
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 3
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 3
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(4) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 4
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 4
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 4
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 4
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 4
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 4
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 4
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 4
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(5) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 5
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 5
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 5
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 5
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 5
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 5
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 5
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 5
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(6) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 6
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 6
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 6
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 6
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 6
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 6
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 6
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 6
|
||||||
|
else 'Z';
|
||||||
|
mod_data_o(7) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 7
|
||||||
|
else sw_mod_data_o(1) when reg_sim_modemnum(1) = 7
|
||||||
|
else sw_mod_data_o(2) when reg_sim_modemnum(2) = 7
|
||||||
|
else sw_mod_data_o(3) when reg_sim_modemnum(3) = 7
|
||||||
|
else sw_mod_data_o(4) when reg_sim_modemnum(4) = 7
|
||||||
|
else sw_mod_data_o(5) when reg_sim_modemnum(5) = 7
|
||||||
|
else sw_mod_data_o(6) when reg_sim_modemnum(6) = 7
|
||||||
|
else sw_mod_data_o(7) when reg_sim_modemnum(7) = 7
|
||||||
|
else 'Z';
|
||||||
|
|
||||||
|
end architecture arch;
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package sim_switcher_pkg is
|
||||||
|
|
||||||
|
type arr_modnum_t is array (natural range <>) of natural range 0 to 15;
|
||||||
|
|
||||||
|
component sim_mux is
|
||||||
|
port (
|
||||||
|
reg_sim_modemnum : arr_modnum_t(0 to 7);
|
||||||
|
sim_rst_o : out std_logic_vector(7 downto 0);
|
||||||
|
mod_simrst_i : in std_logic_vector(7 downto 0);
|
||||||
|
sim_clk_o : out std_logic_vector(7 downto 0);
|
||||||
|
mod_clk_i : in std_logic_vector(7 downto 0);
|
||||||
|
mod_detect_o : out std_logic_vector(3 downto 0);
|
||||||
|
sim_detect_i : in std_logic_vector(7 downto 0);
|
||||||
|
sw_mod_data_i : out std_logic_vector(7 downto 0); -- For switched tri-state buffer there are input and output part of
|
||||||
|
mod_data_i : in std_logic_vector(7 downto 0); -- the lines which are switched transparently, thus ports
|
||||||
|
mod_data_o : out std_logic_vector(7 downto 0); -- sw_mod_data_i is actual output and sw_mod_data_o is
|
||||||
|
sw_mod_data_o : in std_logic_vector(7 downto 0) -- actual input. Please, don't be confused.
|
||||||
|
);
|
||||||
|
end component sim_mux;
|
||||||
|
|
||||||
|
component i2c_master IS
|
||||||
|
generic (
|
||||||
|
input_clk : integer := 50_000_000; --input clock speed from user logic in Hz
|
||||||
|
bus_clk : integer := 400_000 --speed the i2c bus (scl) will run at in Hz
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic; --system clock
|
||||||
|
reset_n : in std_logic; --active low reset
|
||||||
|
ena : in std_logic; --latch in command
|
||||||
|
addr : in std_logic_vector(6 downto 0); --address of target slave
|
||||||
|
rw : in std_logic; --'0' is write, '1' is read
|
||||||
|
data_wr : in std_logic_vector(7 downto 0); --data to write to slave
|
||||||
|
busy : out std_logic; --indicates transaction in progress
|
||||||
|
data_rd : out std_logic_vector(7 downto 0); --data read from slave
|
||||||
|
ack_error : buffer std_logic; --flag if improper acknowledge from slave
|
||||||
|
sda : inout std_logic; --serial data output of i2c bus
|
||||||
|
scl : inout std_logic; --serial clock output of i2c bus
|
||||||
|
scl_invert: in std_logic --true if need to invert output SCL signal
|
||||||
|
);
|
||||||
|
end component i2c_master;
|
||||||
|
|
||||||
|
component i2c_slave is
|
||||||
|
generic (
|
||||||
|
SLAVE_ADDR : std_logic_vector(6 downto 0)
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
scl : inout std_logic;
|
||||||
|
sda : inout std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
rst : in std_logic;
|
||||||
|
-- User interface
|
||||||
|
read_req : out std_logic;
|
||||||
|
data_to_master : in std_logic_vector(7 downto 0);
|
||||||
|
data_valid : out std_logic;
|
||||||
|
data_from_master : out std_logic_vector(7 downto 0)
|
||||||
|
);
|
||||||
|
end component i2c_slave;
|
||||||
|
|
||||||
|
end package sim_switcher_pkg;
|
||||||
1001
sim_switcher_top.vhd
1001
sim_switcher_top.vhd
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue