Skip to content

Commit 7242305

Browse files
committed
wip
1 parent 5ec472d commit 7242305

File tree

7 files changed

+204
-102
lines changed

7 files changed

+204
-102
lines changed

hdl/ip/vhd/i2c/i2c_core.vhd

+10-9
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ begin
113113
reg_sm_next: process(all)
114114
variable v : sm_reg_t;
115115
variable is_read : std_logic;
116+
variable txd_v : std_logic_vector(7 downto 0);
117+
variable txd_valid_v: std_logic;
116118
begin
117119
v := sm_reg;
118120
is_read := '0' when sm_reg.cmd.op = WRITE else '1';
119-
120-
-- defaults
121-
v.tx_byte_valid := '0';
121+
txd_valid_v := '0';
122122

123123
case sm_reg.state is
124124

@@ -135,8 +135,8 @@ begin
135135

136136
-- wait for link layer to finish START sequence and load up the address byte
137137
when WAIT_START =>
138-
v.tx_byte := sm_reg.cmd.addr & is_read;
139-
v.tx_byte_valid := '1';
138+
txd_v := sm_reg.cmd.addr & is_read;
139+
txd_valid_v := '1';
140140
if ll_ready then
141141
v.state := WAIT_ADDR_ACK;
142142
end if;
@@ -153,8 +153,8 @@ begin
153153
else
154154
v.state := WAIT_WRITE_ACK;
155155
-- load up the register address
156-
v.tx_byte := sm_reg.cmd.reg;
157-
v.tx_byte_valid := '1';
156+
txd_v := sm_reg.cmd.reg;
157+
txd_valid_v := '1';
158158
end if;
159159
else
160160
-- TODO: address nack error
@@ -176,8 +176,6 @@ begin
176176
when WRITE =>
177177
if tx_st_if.valid then
178178
v.state := WAIT_WRITE_ACK;
179-
v.tx_byte := tx_st_if.data;
180-
v.tx_byte_valid := '1';
181179
end if;
182180

183181
-- take action based off of the operation type and the ACK
@@ -218,6 +216,9 @@ begin
218216
v.do_start := '1' when v.state = START else '0';
219217
v.do_stop := '1' when v.state = STOP else '0';
220218

219+
v.tx_byte := txd_v when sm_reg.state = WAIT_START or sm_reg.state = WAIT_ADDR_ACK else tx_st_if.data;
220+
v.tx_byte_valid := txd_valid_v when sm_reg.state = WAIT_START or sm_reg.state = WAIT_ADDR_ACK else tx_st_if.valid;
221+
221222
sm_reg_next <= v;
222223
end process;
223224

hdl/ip/vhd/i2c/link_layer/i2c_link_layer.vhd

+28-33
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ architecture rtl of i2c_link_layer is
9898
count_load : std_logic;
9999
count_decr : std_logic;
100100
count_clr : std_logic;
101-
sda_change : std_logic;
101+
sda_changed : std_logic;
102102
ack_sending : std_logic;
103103

104104
-- interfaces
@@ -121,7 +121,7 @@ architecture rtl of i2c_link_layer is
121121
'0', -- count_load
122122
'0', -- count_decr
123123
'0', -- count_clr
124-
'0', -- sda_change
124+
'0', -- sda_changed
125125
'0', -- ack_sending
126126
(others => '0'),-- rx_data
127127
'0', -- rx_data_valid
@@ -202,7 +202,7 @@ begin
202202
port map (
203203
clk => clk,
204204
reset => reset,
205-
enable => sm_reg.sda_change,
205+
enable => not sm_reg.sda_changed,
206206
strobe => transition_sda
207207
);
208208

@@ -240,11 +240,10 @@ begin
240240
v.rx_ack_valid := '0';
241241
v.rx_data_valid := '0';
242242

243-
-- after a scl fedge sda should be updated
244-
if scl_fedge = '1' and (sm_reg.state = BYTE_TX or
245-
sm_reg.state = ACK_TX or
246-
sm_reg.state = STOP_SDA) then
247-
v.sda_change := '1';
243+
if scl_fedge then
244+
v.sda_changed := '0';
245+
elsif transition_sda then
246+
v.sda_changed := '1';
248247
end if;
249248

250249
case sm_reg.state is
@@ -307,23 +306,22 @@ begin
307306
-- data to transmit
308307
v.state := BYTE_TX;
309308
v.tx_data := tx_data;
310-
v.sda_change := '1';
311309
else
312310
-- if nothing else, read
313-
v.state := BYTE_RX;
311+
v.state := BYTE_RX;
314312
end if;
315313

316314
-- Clock out a byte and then wait for an ACK
317-
when BYTE_TX =>
318-
if transition_sda = '1' and sm_reg.bits_shifted = 8 then
319-
v.state := ACK_RX;
320-
v.sda_change := '0';
321-
v.bits_shifted := 0;
322-
elsif transition_sda = '1' and sm_reg.sda_change = '1' then
323-
v.sda_oe := not sm_reg.tx_data(0);
324-
v.tx_data := '1' & sm_reg.tx_data(7 downto 1);
325-
v.sda_change := '0';
326-
v.bits_shifted := sm_reg.bits_shifted + 1;
315+
when BYTE_TX =>
316+
if transition_sda = '1' then
317+
if sm_reg.bits_shifted = 8 then
318+
v.state := ACK_RX;
319+
v.bits_shifted := 0;
320+
else
321+
v.sda_oe := not sm_reg.tx_data(0);
322+
v.tx_data := '1' & sm_reg.tx_data(7 downto 1);
323+
v.bits_shifted := sm_reg.bits_shifted + 1;
324+
end if;
327325
end if;
328326

329327
-- See if the target ACKs
@@ -339,7 +337,6 @@ begin
339337
-- Clock in a byte and then send an ACK
340338
when BYTE_RX =>
341339
v.sda_oe := '0';
342-
-- v.rx_data_valid := '0';
343340

344341
if sm_reg.bits_shifted = 8 then
345342
v.state := ACK_TX;
@@ -353,18 +350,16 @@ begin
353350
-- ACK the target
354351
when ACK_TX =>
355352
-- at the first transition_sda pulse start sending the (N)ACK
356-
if transition_sda = '1' and sm_reg.sda_change = '1' then
357-
v.sda_oe := tx_ack;
358-
v.ack_sending := '1';
359-
v.sda_change := '0';
360-
end if;
361-
362-
-- at the next transition point release the bus
363-
if transition_sda = '1' and sm_reg.ack_sending = '1' then
364-
v.sda_oe := '0';
365-
v.ack_sending := '0';
366-
v.sda_change := '0';
367-
v.state := HANDLE_NEXT_PRE;
353+
if transition_sda = '1' then
354+
if sm_reg.ack_sending = '0' then
355+
v.sda_oe := tx_ack;
356+
v.ack_sending := '1';
357+
else
358+
-- at the next transition point release the bus
359+
v.sda_oe := '0';
360+
v.ack_sending := '0';
361+
v.state := HANDLE_NEXT_PRE;
362+
end if;
368363
end if;
369364

370365
-- drive SDA through final SCL cycle

hdl/ip/vhd/i2c/sims/i2c_peripheral.vhd

+77-33
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use ieee.numeric_std.all;
1111
library vunit_lib;
1212
context vunit_lib.vunit_context;
1313
context vunit_lib.com_context;
14+
context vunit_lib.vc_context;
1415
use vunit_lib.sync_pkg.all;
1516

1617
use work.tristate_if_pkg.all;
@@ -42,23 +43,21 @@ architecture model of i2c_peripheral is
4243

4344
signal state : state_t := IDLE;
4445

45-
signal start_condition : std_logic := '0';
46-
signal stop_condition : std_logic := '0';
46+
signal start_condition : boolean := FALSE;
47+
signal stop_condition : boolean := FALSE;
4748
signal sda_last : std_logic := '1';
4849
signal rx_data : std_logic_vector(7 downto 0) := (others => '0');
4950
signal rx_bit_count : unsigned(3 downto 0) := (others => '0');
5051
signal rx_done : std_logic := '0';
5152
signal rx_ackd : boolean := FALSE;
52-
signal tx_data : std_logic_vector(7 downto 0) := (others => '0');
5353
signal tx_bit_count : unsigned(3 downto 0) := (others => '0');
5454
signal tx_done : std_logic := '0';
5555

56-
signal in_receiving_state : boolean := FALSE;
57-
signal in_transmitting_state : boolean := FALSE;
58-
5956
signal scl_oe : std_logic := '0';
6057
signal sda_oe : std_logic := '0';
6158

59+
signal reg_addr : unsigned(7 downto 0) := (others => '0');
60+
signal is_addr_set : boolean := FALSE;
6261
begin
6362
-- I2C interface is open-drain
6463
scl_if.o <= '0';
@@ -67,8 +66,8 @@ begin
6766
scl_if.oe <= scl_oe;
6867
sda_if.oe <= sda_oe;
6968

70-
start_condition <= '1' when sda_last = '1' and sda_if.i = '0' and scl_if.i = '1' else '0';
71-
stop_condition <= '1' when sda_last = '0' and sda_if.i = '1' and scl_if.i = '1' else '0';
69+
start_condition <= sda_last = '1' and sda_if.i = '0' and scl_if.i = '1';
70+
stop_condition <= sda_last = '0' and sda_if.i = '1' and scl_if.i = '1';
7271

7372
-- message_handler: process
7473
-- variable msg_type : msg_type_t;
@@ -88,6 +87,7 @@ begin
8887
transaction_sm: process
8988
variable event_msg : msg_t;
9089
variable is_read : boolean := FALSE;
90+
variable stop_during_write : boolean := FALSE;
9191
begin
9292
-- IDLE: wait for a START
9393
wait on start_condition;
@@ -97,7 +97,6 @@ begin
9797

9898
-- GET_BYTE: check address and acknowledge appropriately
9999
wait on rx_done;
100-
wait until falling_edge(scl_if.i);
101100
if rx_data(7 downto 1) = address(i2c_peripheral_vc) then
102101
state <= SEND_ACK;
103102
is_read := rx_data(0) = '1';
@@ -110,6 +109,7 @@ begin
110109
end if;
111110

112111
-- SEND_ACK/NACK: acknowledge the START byte
112+
wait on tx_done;
113113
wait until falling_edge(scl_if.i);
114114
if state = SEND_ACK then
115115
if is_read then
@@ -121,7 +121,7 @@ begin
121121
-- NACK'd
122122
state <= GET_STOP;
123123
end if;
124-
wait until rising_edge(scl_if.i);
124+
-- wait until rising_edge(scl_if.i);
125125

126126
if is_read then
127127
-- loop to respond to a controller read request
@@ -137,69 +137,113 @@ begin
137137
-- the loop condition needs this to realize when state gets set to GET_STOP
138138
wait for 1 ns;
139139
end loop;
140+
else
141+
-- loop to respond to a controller write request
142+
while state /= GET_STOP loop
143+
if stop_condition then
144+
state <= GET_STOP;
145+
-- the loop condition needs this to realize when state gets set to GET_STOP
146+
wait for 1 ns;
147+
end if;
148+
149+
-- GET_BYTE: get the byte and then send an acknowledge
150+
wait on rx_done;
151+
state <= GET_STOP when stop_condition else SEND_ACK;
152+
-- the loop condition needs this to realize when state gets set to GET_STOP
153+
wait for 1 ns;
154+
155+
if state /= GET_STOP then
156+
wait on tx_done;
157+
wait until falling_edge(scl_if.i);
158+
state <= GET_BYTE;
159+
160+
if is_addr_set then
161+
write_word(memory(i2c_peripheral_vc), to_integer(reg_addr), rx_data);
162+
event_msg := new_msg(got_byte);
163+
send(net, i2c_peripheral_vc.p_actor, event_msg);
164+
reg_addr <= reg_addr + 1;
165+
else
166+
is_addr_set <= TRUE;
167+
reg_addr <= unsigned(rx_data);
168+
end if;
169+
else
170+
stop_during_write := TRUE;
171+
end if;
172+
end loop;
140173
end if;
141174

142175
-- GET_STOP: wait for a STOP
143-
wait on stop_condition;
176+
wait until (stop_condition or stop_during_write);
144177
event_msg := new_msg(got_stop);
145178
send(net, i2c_peripheral_vc.p_actor, event_msg);
146179
state <= IDLE;
180+
stop_during_write := FALSE;
147181
end process;
148182

149-
in_receiving_state <= state = GET_BYTE or state = GET_ACK;
150183
rx_done <= '1' when (state = GET_BYTE and rx_bit_count = 8) or
151-
(state = GET_ACK and rx_bit_count = 1)
184+
(state = GET_ACK and rx_bit_count = 1) or
185+
stop_condition
152186
else '0';
153187

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

159-
if rx_done then
160-
rx_bit_count <= (others => '0');
161-
elsif state = GET_ACK then
193+
if state = GET_ACK then
162194
-- '0' = ACK, '1' = NACK
163195
rx_ackd <= TRUE when sda_if.i = '0' else FALSE;
164-
rx_bit_count <= to_unsigned(1, rx_bit_count'length);
165196
elsif state = GET_BYTE then
166197
data_next := sda_if.i & rx_data(7 downto 1);
167-
rx_bit_count <= rx_bit_count + 1;
168198
end if;
169199

170200
rx_data <= data_next;
201+
202+
wait until falling_edge(scl_if.i);
203+
204+
if state = GET_ACK then
205+
rx_bit_count <= to_unsigned(1, rx_bit_count'length);
206+
elsif state = GET_BYTE then
207+
rx_bit_count <= rx_bit_count + 1;
208+
else
209+
rx_bit_count <= (others => '0');
210+
end if;
171211
end process;
172212

173213

174-
in_transmitting_state <= state = SEND_ACK or state = SEND_NACK or state = SEND_BYTE;
175214
tx_done <= '1' when ((state = SEND_ACK or state = SEND_ACK) and tx_bit_count = 1) or
176215
(state = SEND_BYTE and tx_bit_count = 8)
177216
else '0';
178217

179218
transmit_sm: process
180-
variable data_next : std_logic_vector(7 downto 0) := X"CC";
219+
variable data_v : std_logic_vector(7 downto 0) := X"CC";
181220
begin
182-
if tx_done then
183-
tx_bit_count <= (others => '0');
184-
end if;
185-
186221
wait until falling_edge(scl_if.i);
187222
-- delay the SDA transition to a bit after SCL falls to allow the controller to release SDA
188-
wait for 25 ns;
189-
190-
if tx_done then
191-
-- release bus
192-
sda_oe <= '0';
193-
elsif state = SEND_ACK or state = SEND_NACK then
223+
wait for 100 ns;
224+
if state = SEND_ACK or state = SEND_NACK then
194225
sda_oe <= '1' when state = SEND_ACK else '0';
195-
tx_bit_count <= to_unsigned(1, tx_bit_count'length);
196226
elsif state = SEND_BYTE then
197-
sda_oe <= not data_next(to_integer(tx_bit_count));
198-
tx_bit_count <= tx_bit_count + 1;
227+
if tx_bit_count = 0 then
228+
data_v := read_word(i2c_peripheral_vc.p_buffer.p_memory_ref, natural(to_integer(reg_addr)), 1);
229+
end if;
230+
sda_oe <= not data_v(to_integer(tx_bit_count));
231+
else
232+
-- release the bus
233+
sda_oe <= '0';
199234
end if;
200235

201236
wait until rising_edge(scl_if.i);
202237

238+
-- update counter once bit has been sampled
239+
if state = SEND_ACK or state = SEND_NACK then
240+
tx_bit_count <= to_unsigned(1, tx_bit_count'length);
241+
elsif state = SEND_BYTE then
242+
tx_bit_count <= tx_bit_count + 1;
243+
else
244+
tx_bit_count <= (others => '0');
245+
end if;
246+
203247
end process;
204248

205249
end architecture;

0 commit comments

Comments
 (0)