-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds the transaction and physical layers of an I2C controller (#253)
This is some early work on the lower layers of an I2C controller block. I'm looking to get this reviewed and integrated a bit prematurely since Nathanael is looking at building out an I2C target block and we'd like to avoid stepping on one another's toes. Given all of this has not been integrated into a design yet and is simulation only, everything is up for grabs if we'd like to make changes. I've begun work on an `i2c_core.vhd` (should probably be renamed `i2c_controller_top.vhd` or something) that is going to attempt to link up a register control interface to the low-level blocks. It would present read/write data buffers as a streaming interface that we could hook up to FIFOs/RAMs/etc as we see fit.
- Loading branch information
1 parent
8942912
commit 6e2c16a
Showing
15 changed files
with
2,065 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
load("//tools:hdl.bzl", "vhdl_unit", "vunit_sim") | ||
|
||
vhdl_unit( | ||
name = "i2c_common_pkg", | ||
srcs = ["i2c_common_pkg.vhd"], | ||
visibility = ['PUBLIC'] | ||
) | ||
|
||
vhdl_unit( | ||
name = "i2c_cmd_vc", | ||
srcs = ["sims/i2c_cmd_vc.vhd", "sims/i2c_cmd_vc_pkg.vhd"], | ||
visibility = ['PUBLIC'] | ||
) | ||
|
||
vhdl_unit( | ||
name = "i2c_target_vc", | ||
srcs = ["sims/i2c_target_vc.vhd", "sims/i2c_target_vc_pkg.vhd"], | ||
visibility = ['PUBLIC'] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this | ||
-- file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
-- | ||
-- Copyright 2024 Oxide Computer Company | ||
|
||
library ieee; | ||
use ieee.std_logic_1164.all; | ||
|
||
package i2c_common_pkg is | ||
|
||
-- | ||
-- Link Layer | ||
-- | ||
|
||
type mode_t is ( | ||
STANDARD, -- up to 100 Kbps | ||
FAST, -- up to 400 Kbps | ||
FAST_PLUS -- up to 1 Mbps | ||
); | ||
|
||
-- A group of settings for generics to generate constants | ||
-- all times in nanoseconds (ns) | ||
type settings_t is record | ||
fscl_period_ns : positive; -- SCL clock period | ||
sda_su_ns : positive; -- data set-up time | ||
sta_su_hd_ns : positive; -- START set-up/hold time | ||
sto_su_ns : positive; -- STOP set-up time | ||
sto_sta_buf_ns : positive; -- bus free time between STOP and START | ||
end record; | ||
|
||
function get_i2c_settings (constant mode : mode_t) return settings_t; | ||
|
||
-- | ||
-- Transaction Layer | ||
-- | ||
|
||
type op_t is ( | ||
READ, | ||
WRITE, | ||
-- RANDOM_READ will write an address byte and one more byte (intended to set an internal | ||
-- address register on a peripheral) before issuing a repeated start for a read. | ||
RANDOM_READ | ||
); | ||
|
||
type cmd_t is record | ||
op : op_t; | ||
addr : std_logic_vector(6 downto 0); | ||
reg : std_logic_vector(7 downto 0); | ||
len : std_logic_vector(7 downto 0); | ||
end record; | ||
constant CMD_RESET : cmd_t := (READ, (others => '0'), (others => '0'), (others => '0')); | ||
|
||
end package; | ||
|
||
package body i2c_common_pkg is | ||
|
||
function get_i2c_settings (constant mode : mode_t) return settings_t is | ||
variable r : settings_t; | ||
begin | ||
case mode is | ||
when STANDARD => | ||
r := ( | ||
10_000, -- 10^9 / 100_000Hz | ||
250, | ||
4700, | ||
4000, | ||
4700 | ||
); | ||
when FAST => | ||
r := ( | ||
2500, -- 10^9 / 400_000Hz | ||
100, | ||
600, | ||
600, | ||
1300 | ||
); | ||
when FAST_PLUS => | ||
r := ( | ||
1000, -- 10^9 / 1_000_000Hz | ||
50, | ||
260, | ||
260, | ||
500 | ||
); | ||
end case; | ||
|
||
return r; | ||
end; | ||
|
||
end package body; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this | ||
-- file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
-- | ||
-- Copyright 2024 Oxide Computer Company | ||
|
||
library ieee; | ||
use ieee.std_logic_1164.all; | ||
use ieee.numeric_std.all; | ||
|
||
library vunit_lib; | ||
context vunit_lib.vunit_context; | ||
context vunit_lib.com_context; | ||
use vunit_lib.sync_pkg.all; | ||
|
||
use work.i2c_common_pkg.all; | ||
use work.i2c_cmd_vc_pkg.all; | ||
|
||
entity i2c_cmd_vc is | ||
generic ( | ||
i2c_cmd_vc : i2c_cmd_vc_t | ||
); | ||
port ( | ||
cmd : out cmd_t := CMD_RESET; | ||
valid : out std_logic := '0'; | ||
ready : in std_logic; | ||
); | ||
end entity; | ||
|
||
architecture model of i2c_cmd_vc is | ||
begin | ||
|
||
handle_messages: process | ||
variable msg : msg_t; | ||
variable msg_type : msg_type_t; | ||
variable command : cmd_t; | ||
variable is_read : boolean; | ||
variable is_random : boolean; | ||
begin | ||
receive(net, i2c_cmd_vc.p_actor, msg); | ||
msg_type := message_type(msg); | ||
|
||
if msg_type = push_i2c_cmd_msg then | ||
is_read := pop(msg); | ||
is_random := pop(msg); | ||
if is_read then | ||
if is_random then | ||
command.op := RANDOM_READ; | ||
else | ||
command.op := READ; | ||
end if; | ||
else | ||
command.op := WRITE; | ||
end if; | ||
command.addr := pop(msg); | ||
command.reg := pop(msg); | ||
command.len := pop(msg); | ||
cmd <= command; | ||
valid <= '1'; | ||
wait until ready; | ||
valid <= '0'; | ||
else | ||
unexpected_msg_type(msg_type); | ||
end if; | ||
end process; | ||
|
||
end architecture; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
-- This Source Code Form is subject to the terms of the Mozilla Public | ||
-- License, v. 2.0. If a copy of the MPL was not distributed with this | ||
-- file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
-- | ||
-- Copyright 2024 Oxide Computer Company | ||
|
||
library ieee; | ||
use ieee.std_logic_1164.all; | ||
use ieee.numeric_std.all; | ||
use ieee.numeric_std_unsigned.all; | ||
|
||
library vunit_lib; | ||
context vunit_lib.vunit_context; | ||
context vunit_lib.com_context; | ||
context vunit_lib.vc_context; | ||
use vunit_lib.sync_pkg.all; | ||
|
||
use work.i2c_common_pkg.all; | ||
|
||
package i2c_cmd_vc_pkg is | ||
|
||
type i2c_cmd_vc_t is record | ||
-- private | ||
p_actor : actor_t; | ||
p_logger : logger_t; | ||
end record; | ||
|
||
constant i2c_cmd_vc_logger : logger_t := get_logger("work:i2c_cmd_vc_pkg"); | ||
|
||
impure function new_i2c_cmd_vc( | ||
actor : actor_t := null_actor; | ||
logger : logger_t := i2c_cmd_vc_logger; | ||
) return i2c_cmd_vc_t; | ||
|
||
constant push_i2c_cmd_msg : msg_type_t := new_msg_type("push_i2c_cmd"); | ||
|
||
procedure push_i2c_cmd( | ||
signal net : inout network_t; | ||
i2c_cmd_vc : i2c_cmd_vc_t; | ||
cmd : cmd_t; | ||
); | ||
|
||
end package; | ||
|
||
package body i2c_cmd_vc_pkg is | ||
|
||
impure function new_i2c_cmd_vc( | ||
actor : actor_t := null_actor; | ||
logger : logger_t := i2c_cmd_vc_logger; | ||
) return i2c_cmd_vc_t is | ||
variable p_actor : actor_t; | ||
begin | ||
p_actor := actor when actor /= null_actor else new_actor; | ||
|
||
return ( | ||
p_actor => p_actor, | ||
p_logger => logger | ||
); | ||
end function; | ||
|
||
procedure push_i2c_cmd( | ||
signal net : inout network_t; | ||
i2c_cmd_vc : i2c_cmd_vc_t; | ||
cmd : cmd_t | ||
) is | ||
variable msg : msg_t := new_msg(push_i2c_cmd_msg); | ||
variable is_read : boolean; | ||
variable is_random : boolean; | ||
begin | ||
-- breaking down our type since we can't push enums in VUnit | ||
is_read := false when cmd.op = WRITE else true; | ||
is_random := true when cmd.op = RANDOM_READ else false; | ||
|
||
-- We break down cmd_t into it's primitive types to push them into the message where we will | ||
-- pop them off when we receive it in order to reconstruct a cmd_t. | ||
-- TODO: implement push/pop for our custom type so we wouldn't have to do this? | ||
push(msg, is_read); -- boolean | ||
push(msg, is_random); -- boolean | ||
push(msg, cmd.addr); -- std_logic_vector | ||
push(msg, cmd.reg); -- std_logic_vector | ||
push(msg, cmd.len); -- std_logic_vector | ||
send(net, i2c_cmd_vc.p_actor, msg); | ||
end; | ||
|
||
|
||
end package body; |
Oops, something went wrong.