Skip to content

Commit 0ea6435

Browse files
authored
Merge pull request #1 from yezzfusl/test
Initial setup and implementation of CAN protocol stack.
2 parents f074b8b + 3de6ebf commit 0ea6435

File tree

5 files changed

+297
-0
lines changed

5 files changed

+297
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
library IEEE;
2+
use IEEE.STD_LOGIC_1164.ALL;
3+
use IEEE.NUMERIC_STD.ALL;
4+
5+
entity can_controller is
6+
Port (
7+
clk : in STD_LOGIC;
8+
rst : in STD_LOGIC;
9+
rx : in STD_LOGIC;
10+
tx : out STD_LOGIC;
11+
data_in : in STD_LOGIC_VECTOR(63 downto 0);
12+
data_out : out STD_LOGIC_VECTOR(63 downto 0);
13+
data_valid : out STD_LOGIC
14+
);
15+
end can_controller;
16+
17+
architecture Behavioral of can_controller is
18+
type can_state_type is (IDLE, ARBITRATION, CONTROL, DATA, CRC, ACK, EOF);
19+
signal state : can_state_type := IDLE;
20+
signal bit_counter : integer range 0 to 127 := 0;
21+
signal crc : STD_LOGIC_VECTOR(14 downto 0) := (others => '0');
22+
23+
-- CAN frame components
24+
signal arbitration_field : STD_LOGIC_VECTOR(11 downto 0);
25+
signal control_field : STD_LOGIC_VECTOR(5 downto 0);
26+
signal data_field : STD_LOGIC_VECTOR(63 downto 0);
27+
28+
begin
29+
process(clk, rst)
30+
begin
31+
if rst = '1' then
32+
state <= IDLE;
33+
bit_counter <= 0;
34+
crc <= (others => '0');
35+
tx <= '1';
36+
data_valid <= '0';
37+
elsif rising_edge(clk) then
38+
case state is
39+
when IDLE =>
40+
if rx = '0' then -- Start of Frame detected
41+
state <= ARBITRATION;
42+
bit_counter <= 0;
43+
end if;
44+
45+
when ARBITRATION =>
46+
if bit_counter < 11 then
47+
arbitration_field(11 - bit_counter) <= rx;
48+
bit_counter <= bit_counter + 1;
49+
else
50+
state <= CONTROL;
51+
bit_counter <= 0;
52+
end if;
53+
54+
when CONTROL =>
55+
if bit_counter < 6 then
56+
control_field(5 - bit_counter) <= rx;
57+
bit_counter <= bit_counter + 1;
58+
else
59+
state <= DATA;
60+
bit_counter <= 0;
61+
end if;
62+
63+
when DATA =>
64+
if bit_counter < 64 then
65+
data_field(63 - bit_counter) <= rx;
66+
bit_counter <= bit_counter + 1;
67+
else
68+
state <= CRC;
69+
bit_counter <= 0;
70+
end if;
71+
72+
when CRC =>
73+
if bit_counter < 15 then
74+
crc(14 - bit_counter) <= rx;
75+
bit_counter <= bit_counter + 1;
76+
else
77+
state <= ACK;
78+
bit_counter <= 0;
79+
end if;
80+
81+
when ACK =>
82+
if bit_counter = 0 then
83+
tx <= '0'; -- Send ACK
84+
bit_counter <= bit_counter + 1;
85+
elsif bit_counter = 1 then
86+
tx <= '1'; -- ACK delimiter
87+
bit_counter <= 0;
88+
state <= EOF;
89+
end if;
90+
91+
when EOF =>
92+
if bit_counter < 7 then
93+
bit_counter <= bit_counter + 1;
94+
else
95+
state <= IDLE;
96+
bit_counter <= 0;
97+
data_out <= data_field;
98+
data_valid <= '1';
99+
end if;
100+
end case;
101+
end if;
102+
end process;
103+
104+
end Behavioral;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
library IEEE;
2+
use IEEE.STD_LOGIC_1164.ALL;
3+
4+
entity can_transceiver is
5+
Port (
6+
clk : in STD_LOGIC;
7+
rst : in STD_LOGIC;
8+
tx_in : in STD_LOGIC;
9+
rx_out : out STD_LOGIC;
10+
can_high : inout STD_LOGIC;
11+
can_low : inout STD_LOGIC
12+
);
13+
end can_transceiver;
14+
15+
architecture Behavioral of can_transceiver is
16+
signal differential : STD_LOGIC;
17+
begin
18+
-- Transmit logic
19+
process(clk, rst)
20+
begin
21+
if rst = '1' then
22+
can_high <= 'Z';
23+
can_low <= 'Z';
24+
elsif rising_edge(clk) then
25+
if tx_in = '0' then
26+
can_high <= '1';
27+
can_low <= '0';
28+
else
29+
can_high <= 'Z';
30+
can_low <= 'Z';
31+
end if;
32+
end if;
33+
end process;
34+
35+
-- Receive logic
36+
differential <= can_high xor can_low;
37+
rx_out <= differential;
38+
39+
end Behavioral;

src/common/clock_generator.vhd

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library IEEE;
2+
use IEEE.STD_LOGIC_1164.ALL;
3+
use IEEE.NUMERIC_STD.ALL;
4+
5+
entity clock_generator is
6+
Port (
7+
clk_in : in STD_LOGIC;
8+
rst : in STD_LOGIC;
9+
clk_out : out STD_LOGIC
10+
);
11+
end clock_generator;
12+
13+
architecture Behavioral of clock_generator is
14+
signal counter : unsigned(7 downto 0) := (others => '0');
15+
signal clk_internal : STD_LOGIC := '0';
16+
begin
17+
process(clk_in, rst)
18+
begin
19+
if rst = '1' then
20+
counter <= (others => '0');
21+
clk_internal <= '0';
22+
elsif rising_edge(clk_in) then
23+
if counter = 49 then -- Divide by 50 for 1MHz CAN clock (assuming 50MHz input)
24+
counter <= (others => '0');
25+
clk_internal <= not clk_internal;
26+
else
27+
counter <= counter + 1;
28+
end if;
29+
end if;
30+
end process;
31+
32+
clk_out <= clk_internal;
33+
34+
end Behavioral;

src/common/reset_controller.vhd

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
library IEEE;
2+
use IEEE.STD_LOGIC_1164.ALL;
3+
4+
entity reset_controller is
5+
Port (
6+
clk : in STD_LOGIC;
7+
ext_rst : in STD_LOGIC;
8+
rst_out : out STD_LOGIC
9+
);
10+
end reset_controller;
11+
12+
architecture Behavioral of reset_controller is
13+
signal reset_shift_reg : STD_LOGIC_VECTOR(3 downto 0) := (others => '1');
14+
begin
15+
process(clk)
16+
begin
17+
if rising_edge(clk) then
18+
reset_shift_reg <= reset_shift_reg(2 downto 0) & ext_rst;
19+
end if;
20+
end process;
21+
22+
rst_out <= '1' when reset_shift_reg = "1111" else '0';
23+
24+
end Behavioral;

src/top_level.vhd

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
library IEEE;
2+
use IEEE.STD_LOGIC_1164.ALL;
3+
4+
entity top_level is
5+
Port (
6+
clk_50m : in STD_LOGIC;
7+
ext_rst : in STD_LOGIC;
8+
can_rx : in STD_LOGIC;
9+
can_tx : out STD_LOGIC;
10+
data_in : in STD_LOGIC_VECTOR(63 downto 0);
11+
data_out : out STD_LOGIC_VECTOR(63 downto 0);
12+
data_valid : out STD_LOGIC
13+
);
14+
end top_level;
15+
16+
architecture Behavioral of top_level is
17+
signal clk_1m : STD_LOGIC;
18+
signal rst : STD_LOGIC;
19+
signal can_rx_internal, can_tx_internal : STD_LOGIC;
20+
21+
component clock_generator
22+
Port (
23+
clk_in : in STD_LOGIC;
24+
rst : in STD_LOGIC;
25+
clk_out : out STD_LOGIC
26+
);
27+
end component;
28+
29+
component reset_controller
30+
Port (
31+
clk : in STD_LOGIC;
32+
ext_rst : in STD_LOGIC;
33+
rst_out : out STD_LOGIC
34+
);
35+
end component;
36+
37+
component can_controller
38+
Port (
39+
clk : in STD_LOGIC;
40+
rst : in STD_LOGIC;
41+
rx : in STD_LOGIC;
42+
tx : out STD_LOGIC;
43+
data_in : in STD_LOGIC_VECTOR(63 downto 0);
44+
data_out : out STD_LOGIC_VECTOR(63 downto 0);
45+
data_valid : out STD_LOGIC
46+
);
47+
end component;
48+
49+
component can_transceiver
50+
Port (
51+
clk : in STD_LOGIC;
52+
rst : in STD_LOGIC;
53+
tx_in : in STD_LOGIC;
54+
rx_out : out STD_LOGIC;
55+
can_high : inout STD_LOGIC;
56+
can_low : inout STD_LOGIC
57+
);
58+
end component;
59+
60+
begin
61+
clock_gen: clock_generator
62+
port map (
63+
clk_in => clk_50m,
64+
rst => rst,
65+
clk_out => clk_1m
66+
);
67+
68+
reset_ctrl: reset_controller
69+
port map (
70+
clk => clk_50m,
71+
ext_rst => ext_rst,
72+
rst_out => rst
73+
);
74+
75+
can_ctrl: can_controller
76+
port map (
77+
clk => clk_1m,
78+
rst => rst,
79+
rx => can_rx_internal,
80+
tx => can_tx_internal,
81+
data_in => data_in,
82+
data_out => data_out,
83+
data_valid => data_valid
84+
);
85+
86+
can_xcvr: can_transceiver
87+
port map (
88+
clk => clk_1m,
89+
rst => rst,
90+
tx_in => can_tx_internal,
91+
rx_out => can_rx_internal,
92+
can_high => can_rx,
93+
can_low => can_tx
94+
);
95+
96+
end Behavioral;

0 commit comments

Comments
 (0)