Skip to content

Commit ace6d5b

Browse files
authored
Merge pull request #6 from yezzfusl/test
Enhance CAN controller with advanced features and error handling.
2 parents 7dfe384 + ad4f30c commit ace6d5b

File tree

1 file changed

+202
-64
lines changed

1 file changed

+202
-64
lines changed

src/can_protocol/can_controller.vhd

+202-64
Original file line numberDiff line numberDiff line change
@@ -12,94 +12,232 @@ entity can_controller is
1212
data_out : out STD_LOGIC_VECTOR(63 downto 0);
1313
data_valid : out STD_LOGIC;
1414
sync : in STD_LOGIC;
15-
bit_time : in STD_LOGIC_VECTOR(15 downto 0)
15+
bit_time : in STD_LOGIC_VECTOR(15 downto 0);
16+
-- New ports
17+
tx_request : in STD_LOGIC;
18+
tx_done : out STD_LOGIC;
19+
rx_busy : out STD_LOGIC;
20+
error_flag : out STD_LOGIC;
21+
bus_off : out STD_LOGIC;
22+
extended_id : in STD_LOGIC;
23+
remote_frame : in STD_LOGIC;
24+
id_in : in STD_LOGIC_VECTOR(28 downto 0);
25+
id_out : out STD_LOGIC_VECTOR(28 downto 0);
26+
dlc_in : in STD_LOGIC_VECTOR(3 downto 0);
27+
dlc_out : out STD_LOGIC_VECTOR(3 downto 0)
1628
);
1729
end can_controller;
1830

1931
architecture Behavioral of can_controller is
20-
type can_state_type is (IDLE, ARBITRATION, CONTROL, DATA, CRC, ACK, EOF);
32+
type can_state_type is (IDLE, ARBITRATION, CONTROL, DATA, CRC, ACK, EOF, ERROR, BUS_OFF, TRANSMIT);
2133
signal state : can_state_type := IDLE;
2234
signal bit_counter : integer range 0 to 127 := 0;
2335
signal crc : STD_LOGIC_VECTOR(14 downto 0) := (others => '0');
36+
signal crc_calc : STD_LOGIC_VECTOR(14 downto 0) := (others => '0');
2437

2538
-- CAN frame components
26-
signal arbitration_field : STD_LOGIC_VECTOR(11 downto 0);
39+
signal arbitration_field : STD_LOGIC_VECTOR(28 downto 0);
2740
signal control_field : STD_LOGIC_VECTOR(5 downto 0);
2841
signal data_field : STD_LOGIC_VECTOR(63 downto 0);
2942

43+
-- Additional signals
44+
signal error_counter : unsigned(7 downto 0) := (others => '0');
45+
signal bit_stuff_counter : unsigned(2 downto 0) := (others => '0');
46+
signal last_bit : STD_LOGIC := '0';
47+
signal stuff_error : STD_LOGIC := '0';
48+
signal crc_error : STD_LOGIC := '0';
49+
signal form_error : STD_LOGIC := '0';
50+
signal ack_error : STD_LOGIC := '0';
51+
signal tx_buffer : STD_LOGIC_VECTOR(127 downto 0);
52+
signal tx_bit_counter : integer range 0 to 127 := 0;
53+
signal is_transmitting : STD_LOGIC := '0';
54+
55+
-- CRC calculation function
56+
function update_crc(crc_in : STD_LOGIC_VECTOR(14 downto 0); data_in : STD_LOGIC) return STD_LOGIC_VECTOR is
57+
variable crc_out : STD_LOGIC_VECTOR(14 downto 0);
58+
begin
59+
crc_out := crc_in(13 downto 0) & data_in;
60+
if crc_in(14) /= data_in then
61+
crc_out := crc_out xor "100010110011001";
62+
end if;
63+
return crc_out;
64+
end function;
65+
3066
begin
3167
process(clk, rst)
68+
variable next_bit : STD_LOGIC;
3269
begin
3370
if rst = '1' then
3471
state <= IDLE;
3572
bit_counter <= 0;
3673
crc <= (others => '0');
3774
tx <= '1';
3875
data_valid <= '0';
39-
elsif rising_edge(clk) and sync = '1' then
40-
case state is
41-
when IDLE =>
42-
if rx = '0' then -- Start of Frame detected
43-
state <= ARBITRATION;
44-
bit_counter <= 0;
45-
end if;
46-
47-
when ARBITRATION =>
48-
if bit_counter < 11 then
49-
arbitration_field(11 - bit_counter) <= rx;
50-
bit_counter <= bit_counter + 1;
51-
else
52-
state <= CONTROL;
53-
bit_counter <= 0;
54-
end if;
55-
56-
when CONTROL =>
57-
if bit_counter < 6 then
58-
control_field(5 - bit_counter) <= rx;
59-
bit_counter <= bit_counter + 1;
60-
else
61-
state <= DATA;
62-
bit_counter <= 0;
63-
end if;
64-
65-
when DATA =>
66-
if bit_counter < 64 then
67-
data_field(63 - bit_counter) <= rx;
68-
bit_counter <= bit_counter + 1;
69-
else
70-
state <= CRC;
71-
bit_counter <= 0;
72-
end if;
76+
error_flag <= '0';
77+
bus_off <= '0';
78+
error_counter <= (others => '0');
79+
rx_busy <= '0';
80+
tx_done <= '0';
81+
is_transmitting <= '0';
82+
elsif rising_edge(clk) then
83+
if sync = '1' then
84+
case state is
85+
when IDLE =>
86+
rx_busy <= '0';
87+
if tx_request = '1' and is_transmitting = '0' then
88+
state <= TRANSMIT;
89+
is_transmitting <= '1';
90+
tx_buffer <= id_in & dlc_in & data_in & x"00000000"; -- Prepare transmit buffer
91+
tx_bit_counter <= 0;
92+
elsif rx = '0' then -- Start of Frame detected
93+
state <= ARBITRATION;
94+
bit_counter <= 0;
95+
crc_calc <= (others => '0');
96+
rx_busy <= '1';
97+
end if;
98+
99+
when ARBITRATION =>
100+
if (extended_id = '0' and bit_counter < 11) or (extended_id = '1' and bit_counter < 29) then
101+
arbitration_field(28 - bit_counter) <= rx;
102+
bit_counter <= bit_counter + 1;
103+
crc_calc <= update_crc(crc_calc, rx);
104+
else
105+
state <= CONTROL;
106+
bit_counter <= 0;
107+
end if;
108+
109+
when CONTROL =>
110+
if bit_counter < 6 then
111+
control_field(5 - bit_counter) <= rx;
112+
bit_counter <= bit_counter + 1;
113+
crc_calc <= update_crc(crc_calc, rx);
114+
else
115+
state <= DATA;
116+
bit_counter <= 0;
117+
end if;
118+
119+
when DATA =>
120+
if bit_counter < to_integer(unsigned(control_field(3 downto 0))) * 8 then
121+
data_field(63 - bit_counter) <= rx;
122+
bit_counter <= bit_counter + 1;
123+
crc_calc <= update_crc(crc_calc, rx);
124+
else
125+
state <= CRC;
126+
bit_counter <= 0;
127+
end if;
128+
129+
when CRC =>
130+
if bit_counter < 15 then
131+
crc(14 - bit_counter) <= rx;
132+
bit_counter <= bit_counter + 1;
133+
else
134+
state <= ACK;
135+
bit_counter <= 0;
136+
if crc /= crc_calc then
137+
crc_error <= '1';
138+
end if;
139+
end if;
140+
141+
when ACK =>
142+
if bit_counter = 0 then
143+
tx <= '0'; -- Send ACK
144+
bit_counter <= bit_counter + 1;
145+
elsif bit_counter = 1 then
146+
tx <= '1'; -- ACK delimiter
147+
bit_counter <= 0;
148+
state <= EOF;
149+
if rx = '1' then
150+
ack_error <= '1';
151+
end if;
152+
end if;
153+
154+
when EOF =>
155+
if bit_counter < 7 then
156+
if rx /= '1' then
157+
form_error <= '1';
158+
end if;
159+
bit_counter <= bit_counter + 1;
160+
else
161+
state <= IDLE;
162+
bit_counter <= 0;
163+
data_out <= data_field;
164+
id_out <= arbitration_field;
165+
dlc_out <= control_field(3 downto 0);
166+
data_valid <= '1';
167+
end if;
168+
169+
when ERROR =>
170+
if bit_counter < 6 then
171+
tx <= '0'; -- Transmit error flag
172+
bit_counter <= bit_counter + 1;
173+
else
174+
state <= IDLE;
175+
bit_counter <= 0;
176+
error_counter <= error_counter + 1;
177+
if error_counter = 255 then
178+
state <= BUS_OFF;
179+
end if;
180+
end if;
181+
182+
when BUS_OFF =>
183+
bus_off <= '1';
184+
if error_counter = 0 then
185+
state <= IDLE;
186+
bus_off <= '0';
187+
end if;
188+
189+
when TRANSMIT =>
190+
if tx_bit_counter < 128 then
191+
tx <= tx_buffer(127 - tx_bit_counter);
192+
tx_bit_counter <= tx_bit_counter + 1;
193+
else
194+
state <= IDLE;
195+
is_transmitting <= '0';
196+
tx_done <= '1';
197+
end if;
73198

74-
when CRC =>
75-
if bit_counter < 15 then
76-
crc(14 - bit_counter) <= rx;
77-
bit_counter <= bit_counter + 1;
78-
else
79-
state <= ACK;
80-
bit_counter <= 0;
81-
end if;
82-
83-
when ACK =>
84-
if bit_counter = 0 then
85-
tx <= '0'; -- Send ACK
86-
bit_counter <= bit_counter + 1;
87-
elsif bit_counter = 1 then
88-
tx <= '1'; -- ACK delimiter
89-
bit_counter <= 0;
90-
state <= EOF;
91-
end if;
92-
93-
when EOF =>
94-
if bit_counter < 7 then
95-
bit_counter <= bit_counter + 1;
199+
end case;
200+
201+
-- Bit stuffing
202+
if state /= IDLE and state /= ERROR and state /= BUS_OFF and state /= TRANSMIT then
203+
if rx = last_bit then
204+
bit_stuff_counter <= bit_stuff_counter + 1;
205+
if bit_stuff_counter = 5 then
206+
stuff_error <= '1';
207+
end if;
96208
else
97-
state <= IDLE;
98-
bit_counter <= 0;
99-
data_out <= data_field;
100-
data_valid <= '1';
209+
bit_stuff_counter <= (others => '0');
101210
end if;
102-
end case;
211+
last_bit <= rx;
212+
end if;
213+
214+
-- Error handling
215+
if stuff_error = '1' or crc_error = '1' or form_error = '1' or ack_error = '1' then
216+
state <= ERROR;
217+
error_flag <= '1';
218+
stuff_error <= '0';
219+
crc_error <= '0';
220+
form_error <= '0';
221+
ack_error <= '0';
222+
end if;
223+
224+
end if;
225+
end if;
226+
end process;
227+
228+
-- Error counter management
229+
process(clk, rst)
230+
begin
231+
if rst = '1' then
232+
error_counter <= (others => '0');
233+
elsif rising_edge(clk) then
234+
if state = ERROR then
235+
if error_counter < 255 then
236+
error_counter <= error_counter + 1;
237+
end if;
238+
elsif state = IDLE and error_counter > 0 then
239+
error_counter <= error_counter - 1;
240+
end if;
103241
end if;
104242
end process;
105243

0 commit comments

Comments
 (0)