Skip to content

Commit

Permalink
smol wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron-Hartwig committed Nov 22, 2024
1 parent 7242305 commit 75a5471
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 70 deletions.
79 changes: 38 additions & 41 deletions hdl/ip/vhd/i2c/sims/i2c_peripheral.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@ architecture model of i2c_peripheral is
signal sda_last : std_logic := '1';
signal rx_data : std_logic_vector(7 downto 0) := (others => '0');
signal rx_bit_count : unsigned(3 downto 0) := (others => '0');
signal rx_done : std_logic := '0';
signal rx_done : boolean := FALSE;
signal rx_ackd : boolean := FALSE;
signal tx_data : std_logic_vector(7 downto 0) := (others => '0');
signal tx_bit_count : unsigned(3 downto 0) := (others => '0');
signal tx_done : std_logic := '0';
signal tx_done : boolean := FALSE;

signal scl_oe : std_logic := '0';
signal sda_oe : std_logic := '0';

signal reg_addr : unsigned(7 downto 0) := (others => '0');
signal is_addr_set : boolean := FALSE;
signal addr_set : boolean := FALSE;
signal addr_incr : boolean := FALSE;
begin
-- I2C interface is open-drain
scl_if.o <= '0';
Expand Down Expand Up @@ -109,26 +111,25 @@ begin
end if;

-- SEND_ACK/NACK: acknowledge the START byte
wait on tx_done;
wait until falling_edge(scl_if.i);
if state = SEND_ACK then
if is_read then
state <= SEND_BYTE;
wait for 1 ns;
else
state <= GET_BYTE;
end if;
else
-- NACK'd
state <= GET_STOP;
end if;
-- wait until rising_edge(scl_if.i);

if is_read then
-- loop to respond to a controller read request
while state /= GET_STOP loop
-- SEND_BYTE: send the byte and then wait for an acknowledge
wait on tx_done;
wait until rising_edge(scl_if.i);
wait until falling_edge(scl_if.i);
state <= GET_ACK;

-- GET_ACK: see if the controller wants to continue reading or is finished
Expand All @@ -147,7 +148,7 @@ begin
end if;

-- GET_BYTE: get the byte and then send an acknowledge
wait on rx_done;
wait until rx_done or stop_condition;
state <= GET_STOP when stop_condition else SEND_ACK;
-- the loop condition needs this to realize when state gets set to GET_STOP
wait for 1 ns;
Expand All @@ -157,13 +158,15 @@ begin
wait until falling_edge(scl_if.i);
state <= GET_BYTE;

if is_addr_set then
if addr_set then
write_word(memory(i2c_peripheral_vc), to_integer(reg_addr), rx_data);
event_msg := new_msg(got_byte);
send(net, i2c_peripheral_vc.p_actor, event_msg);
reg_addr <= reg_addr + 1;
if addr_incr then
reg_addr <= reg_addr + 1;
end if;
else
is_addr_set <= TRUE;
addr_set <= TRUE;
reg_addr <= unsigned(rx_data);
end if;
else
Expand All @@ -174,73 +177,67 @@ begin

-- GET_STOP: wait for a STOP
wait until (stop_condition or stop_during_write);
event_msg := new_msg(got_stop);
event_msg := new_msg(got_stop);
send(net, i2c_peripheral_vc.p_actor, event_msg);
state <= IDLE;
state <= IDLE;
stop_during_write := FALSE;
end process;

rx_done <= '1' when (state = GET_BYTE and rx_bit_count = 8) or
(state = GET_ACK and rx_bit_count = 1) or
stop_condition
else '0';

receive_sm: process
variable data_next : std_logic_vector(7 downto 0) := (others => '0');
begin
wait until rising_edge(scl_if.i);

rx_done <= FALSE;
if state = GET_ACK then
-- '0' = ACK, '1' = NACK
rx_ackd <= TRUE when sda_if.i = '0' else FALSE;
rx_bit_count <= to_unsigned(1, rx_bit_count'length);
elsif state = GET_BYTE then
data_next := sda_if.i & rx_data(7 downto 1);
rx_data <= sda_if.i & rx_data(7 downto 1);
rx_bit_count <= rx_bit_count + 1;
end if;

rx_data <= data_next;

wait until falling_edge(scl_if.i);
wait until falling_edge(scl_if.i) or stop_condition;
if stop_condition then
rx_bit_count <= (others => '0');
wait until falling_edge(scl_if.i);
end if;

if state = GET_ACK then
rx_bit_count <= to_unsigned(1, rx_bit_count'length);
elsif state = GET_BYTE then
rx_bit_count <= rx_bit_count + 1;
else
if (state = GET_BYTE and rx_bit_count = 8) or (state = GET_ACK and rx_bit_count = 1) then
rx_done <= TRUE;
rx_bit_count <= (others => '0');
end if;
end process;


tx_done <= '1' when ((state = SEND_ACK or state = SEND_ACK) and tx_bit_count = 1) or
(state = SEND_BYTE and tx_bit_count = 8)
else '0';

transmit_sm: process
variable data_v : std_logic_vector(7 downto 0) := X"CC";
variable txd : std_logic_vector(7 downto 0) := (others => '0');
begin
wait until falling_edge(scl_if.i);
tx_done <= FALSE;
-- delay the SDA transition to a bit after SCL falls to allow the controller to release SDA
wait for 100 ns;
if state = SEND_ACK or state = SEND_NACK then
sda_oe <= '1' when state = SEND_ACK else '0';
tx_bit_count <= to_unsigned(1, tx_bit_count'length);
elsif state = SEND_BYTE then
if tx_bit_count = 0 then
data_v := read_word(i2c_peripheral_vc.p_buffer.p_memory_ref, natural(to_integer(reg_addr)), 1);
txd := read_word(i2c_peripheral_vc.p_buffer.p_memory_ref, natural(to_integer(reg_addr)), 1);
else
txd := '1' & tx_data(7 downto 1);
end if;
sda_oe <= not data_v(to_integer(tx_bit_count));
sda_oe <= not txd(0);
tx_bit_count <= tx_bit_count + 1;
else
-- release the bus
sda_oe <= '0';
end if;
tx_data <= txd;

wait until rising_edge(scl_if.i);

-- update counter once bit has been sampled
if state = SEND_ACK or state = SEND_NACK then
tx_bit_count <= to_unsigned(1, tx_bit_count'length);
elsif state = SEND_BYTE then
tx_bit_count <= tx_bit_count + 1;
else
if ((state = SEND_ACK or state = SEND_ACK) and tx_bit_count = 1) or
(state = SEND_BYTE and tx_bit_count = 8) then
tx_done <= TRUE;
tx_bit_count <= (others => '0');
end if;

Expand Down
24 changes: 4 additions & 20 deletions hdl/ip/vhd/i2c/sims/i2c_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,7 @@ begin
check_false(ack, "Peripheral did not NACK incorrect address");
-- transaction is over, receive STOP event
wait for 10 us;
elsif run("write_one_byte") then
expected_addr := X"9E"; -- arbitrary for the test
expected_data := X"A5";

command := (
op => WRITE,
addr => address(I2C_PERIPHERAL_VC),
reg => std_logic_vector(expected_addr),
len => to_unsigned(1, command.len'length)
);
push_i2c_cmd(net, I2C_CMD_VC, command);

start_byte_ack(net, I2C_PERIPHERAL_VC, ack);
check_true(ack, "Peripheral did not ACK correct address");

push_basic_stream(net, TX_DATA_SOURCE_VC, expected_data);
check_written_byte(net, I2C_PERIPHERAL_VC, expected_data, expected_addr);

expect_stop(net, I2C_PERIPHERAL_VC);
elsif run("read_one_byte") then
elsif run("write_and_read_one_byte") then
-- write some data in
expected_addr := X"9E"; -- arbitrary for the test
expected_data := X"A5";
Expand Down Expand Up @@ -123,6 +104,9 @@ begin
check_equal(data, expected_data, "Expected read data to match");

expect_stop(net, I2C_PERIPHERAL_VC);
elsif run("write_and_read_many_bytes") then

end if;
end if;
end loop;

Expand Down
30 changes: 21 additions & 9 deletions hdl/ip/vhd/i2c/sims/tb_i2c.gtkw
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[*]
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
[*] Thu Nov 21 22:01:19 2024
[*] Fri Nov 22 17:02:19 2024
[*]
[dumpfile] "/home/aaron/Oxide/git/quartz/vunit_out/test_output/lib.i2c_tb.write_one_byte_45371635dc90e325712a46a4289140589cf4a62c/nvc/i2c_tb.fst"
[dumpfile_mtime] "Thu Nov 21 21:54:59 2024"
[dumpfile_size] 3991
[dumpfile] "/home/aaron/Oxide/git/quartz/vunit_out/test_output/lib.i2c_tb.read_one_byte_f5003d4ca7a772188d7e5908ca58541f5b186a63/nvc/i2c_tb.fst"
[dumpfile_mtime] "Fri Nov 22 16:55:54 2024"
[dumpfile_size] 4917
[savefile] "/home/aaron/Oxide/git/quartz/hdl/ip/vhd/i2c/sims/tb_i2c.gtkw"
[timestart] 64455600000
[timestart] 122700000000
[size] 2688 1283
[pos] -1 -1
*-25.367004 64660000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[pos] 1183 23
*-32.015984 138388000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] i2c_tb.
[treeopen] i2c_tb.th.
[treeopen] i2c_tb.th.dut.i2c_link_layer_inst.
Expand Down Expand Up @@ -69,7 +69,7 @@ i2c_tb.th.dut.i2c_link_layer_inst.scl_fedge
i2c_tb.th.dut.i2c_link_layer_inst.transition_sda
@200
-Transmit Stream
@29
@28
i2c_tb.th.dut.i2c_link_layer_inst.tx_data_valid
@22
i2c_tb.th.dut.i2c_link_layer_inst.tx_data[7:0]
Expand Down Expand Up @@ -130,7 +130,6 @@ i2c_tb.th.peripheral.sda_if.oe
i2c_tb.th.peripheral.state
i2c_tb.th.peripheral.start_condition
i2c_tb.th.peripheral.stop_condition
i2c_tb.th.peripheral.is_addr_set
@22
i2c_tb.th.peripheral.reg_addr[7:0]
@28
Expand All @@ -140,6 +139,19 @@ i2c_tb.th.peripheral.rx_data[7:0]
i2c_tb.th.peripheral.rx_bit_count[3:0]
@28
i2c_tb.th.peripheral.tx_done
@800023
i2c_tb.th.peripheral.tx_data[7:0]
@29
(0)i2c_tb.th.peripheral.tx_data[7:0]
(1)i2c_tb.th.peripheral.tx_data[7:0]
(2)i2c_tb.th.peripheral.tx_data[7:0]
(3)i2c_tb.th.peripheral.tx_data[7:0]
(4)i2c_tb.th.peripheral.tx_data[7:0]
(5)i2c_tb.th.peripheral.tx_data[7:0]
(6)i2c_tb.th.peripheral.tx_data[7:0]
(7)i2c_tb.th.peripheral.tx_data[7:0]
@1001201
-group_end
@22
i2c_tb.th.peripheral.tx_bit_count[3:0]
[pattern_trace] 1
Expand Down

0 comments on commit 75a5471

Please sign in to comment.