Skip to content

Commit b64dfbc

Browse files
Brings in vhdl style formatter. (#151)
This can be run via buck: ` buck2 run //tools/multitool:multitool -- format` or if you just want the report without the fixes: `buck2 run //tools/multitool:multitool -- format --no-fix`
1 parent f4b5eae commit b64dfbc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+9081
-1915
lines changed

.buckconfig

+3
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ target_platform_detector_spec = target:root//...->prelude//platforms:default
1515

1616
[project]
1717
ignore = .git
18+
19+
[build]
20+
execution_platforms = prelude//platforms:default

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,14 @@ specifies vunit_lib as such, but your paths may differ. The vscode extension wi
109109
home directory file and the workspace root file and merge them.
110110

111111
An example of the home-directory .vhdl_ls.toml can be found [here](docs/README.md)
112+
113+
## VHDL "auto" formatter
114+
We're using [vhdl-style-guide](https://vhdl-style-guide.readthedocs.io/) to provide
115+
consistent formatting. Our custom ruleset is in the repo root (vsg_config.json) and we provide a wrapper to run this tool against all of our 1st-party VHDL code.
116+
You can run `buck2 run //tools/multitool:multitool -- format` to auto-format our code
117+
and you can run `buck2 run //tools/multitool:multitool -- format --no-fix` to see a
118+
report of the formatter without changing the code. This is especially useful when
119+
trying to identify a target rule for adjustment or disablement.
120+
121+
Right now, this has to be run manually by a user before code check-in, we'll look
122+
into editor automation as we stabilize the rules and have time to do so.

hdl/ip/vhd/arb_mux_demux/arbiter.vhd

100755100644
+115-111
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,115 @@
1-
-- This Source Code Form is subject to the terms of the Mozilla Public
2-
-- License, v. 2.0. If a copy of the MPL was not distributed with this
3-
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
4-
--
5-
-- Copyright 2024 Oxide Computer Company
6-
7-
-- Note: Documentation can be rendered in VSCode using the TerosHDL
8-
-- plugin: https://terostechnology.github.io/terosHDLdoc/
9-
--! A simple request arbiter that can do priority or round-robbin arbitration
10-
--! Built generically using unconstrained arrays.
11-
--! In Priority mode, the LSB (0) gets the highest priority.
12-
--! In round-robbin mode, the LSB gets the priority only when there was not a grant in the previous
13-
--! cycle and two requests occur simultaneously.
14-
--! A goal is to do this in a single cycle, without having to scan the request bits so that
15-
--! this scales well with increasing vectors.
16-
--! This arbiter uses the fact that <number> AND <two's complement of number> gives
17-
--! you a vector with the lowest (right-most) bit of <number> set
18-
library ieee;
19-
use ieee.std_logic_1164.all;
20-
use ieee.numeric_std.all;
21-
22-
use work.arbiter_pkg.arbiter_mode;
23-
24-
entity arbiter is
25-
generic
26-
(
27-
--! Using arbiter_pkg.arbiter_mode enum, choose
28-
--! arbiter type
29-
MODE : arbiter_mode
30-
);
31-
port
32-
(
33-
clk : in std_logic;
34-
reset : in std_logic;
35-
--! Request vector blocks requesting arbitration must
36-
--! assert their request until grant has been asserted
37-
--! grant remains until request is de-asserted.
38-
requests : in std_logic_vector;
39-
--! This block asserts grant signals, and holds them
40-
--! until the the associated request signal drops.
41-
grants : out std_logic_vector
42-
);
43-
end entity;
44-
architecture rtl of arbiter is
45-
constant ZEROS : unsigned(requests'range) := (others => '0');
46-
signal requests_int : unsigned(requests'range);
47-
signal requests_masked_twos : unsigned(requests'range);
48-
signal requests_masked : unsigned(requests'range);
49-
signal requests_last : unsigned(requests'range);
50-
signal grants_int : unsigned(requests'range);
51-
signal grants_last : unsigned(requests'range);
52-
signal grants_mask : unsigned(requests'range);
53-
signal req_vec_f_edge : unsigned(requests'range);
54-
signal req_f_edge : std_logic;
55-
begin
56-
requests_int <= unsigned(requests);
57-
round_robin_mode : if MODE = ROUND_ROBIN generate
58-
-- This uses a grant-masking scheme to generate round-robin grant behavior.
59-
-- We want to mask off the previous granted channel and any lower bits
60-
-- so the upper bits get a round-robin chance.
61-
grants_mask <= not (grants_last or (grants_last - 1));
62-
63-
-- Mask the requests based on the current grant mask, unless we have no active requests or grants, in
64-
-- which case, pass the unmasked vector through
65-
requests_masked <= requests_int and grants_mask when (requests_int and grants_mask) /= 0 else
66-
requests_int;
67-
else generate
68-
-- In priority mode, we needn't mask grants since the priority encoder takes over
69-
-- and we will allow multiple grants to the same requester to the exclusion of others
70-
-- given the desired priority.
71-
grants_mask <= (others => '0');
72-
requests_masked <= requests_int;
73-
end generate;
74-
75-
-- Build two's complement, remember basic boolean math? 2's complement = (not <dat>) + 1
76-
requests_masked_twos <= (not requests_masked) + 1;
77-
78-
fedge_detects : for i in requests_int'range generate
79-
req_vec_f_edge(i) <= '1' when requests_int(i) = '0' and requests_last(i) = '1' else
80-
'0';
81-
end generate;
82-
--Unary OR reduction, active when any bit is active
83-
req_f_edge <= or req_vec_f_edge;
84-
85-
the_arbiter : process (clk)
86-
begin
87-
if reset then
88-
grants_int <= ZEROS;
89-
grants_last <= (others => '0');
90-
requests_last <= (others => '0');
91-
elsif rising_edge(clk) then
92-
-- Store history for edge detector
93-
requests_last <= requests_int;
94-
-- To determine a grant, we take the currently active requests vector,
95-
-- which is masked by the allowable requests in round-robbin mode, and then
96-
-- bitwise AND that with it's two's complement
97-
-- to get 1 bit active as our active grant.
98-
grants_int <= requests_masked and requests_masked_twos;
99-
if req_f_edge then
100-
-- Note: we expect requesters of this to hold request high until they both have the grant,
101-
-- and are finished with their current transaction. This means that falling edges of
102-
-- requests cause arbitration updates and we save the current grant for use in round-robin
103-
-- arbitration next time.
104-
grants_last <= grants_int;
105-
end if;
106-
end if;
107-
end process;
108-
109-
grants <= std_logic_vector(grants_int);
110-
111-
end architecture;
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this
3+
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright 2024 Oxide Computer Company
6+
7+
-- Note: Documentation can be rendered in VSCode using the TerosHDL
8+
-- plugin: https://terostechnology.github.io/terosHDLdoc/
9+
--! A simple request arbiter that can do priority or round-robbin arbitration
10+
--! Built generically using unconstrained arrays.
11+
--! In Priority mode, the LSB (0) gets the highest priority.
12+
--! In round-robbin mode, the LSB gets the priority only when there was not a grant in the previous
13+
--! cycle and two requests occur simultaneously.
14+
--! A goal is to do this in a single cycle, without having to scan the request bits so that
15+
--! this scales well with increasing vectors.
16+
--! This arbiter uses the fact that <number> AND <two's complement of number> gives
17+
--! you a vector with the lowest (right-most) bit of <number> set
18+
19+
library ieee;
20+
use ieee.std_logic_1164.all;
21+
use ieee.numeric_std.all;
22+
use work.arbiter_pkg.arbiter_mode;
23+
24+
entity arbiter is
25+
generic (
26+
--! Using arbiter_pkg.arbiter_mode enum, choose
27+
--! arbiter type
28+
mode : arbiter_mode
29+
);
30+
port (
31+
clk : in std_logic;
32+
reset : in std_logic;
33+
--! Request vector blocks requesting arbitration must
34+
--! assert their request until grant has been asserted
35+
--! grant remains until request is de-asserted.
36+
requests : in std_logic_vector;
37+
--! This block asserts grant signals, and holds them
38+
--! until the the associated request signal drops.
39+
grants : out std_logic_vector
40+
);
41+
end entity;
42+
43+
architecture rtl of arbiter is
44+
45+
constant zeros : unsigned(requests'range) := (others => '0');
46+
signal requests_int : unsigned(requests'range);
47+
signal requests_masked_twos : unsigned(requests'range);
48+
signal requests_masked : unsigned(requests'range);
49+
signal requests_last : unsigned(requests'range);
50+
signal grants_int : unsigned(requests'range);
51+
signal grants_last : unsigned(requests'range);
52+
signal grants_mask : unsigned(requests'range);
53+
signal req_vec_f_edge : unsigned(requests'range);
54+
signal req_f_edge : std_logic;
55+
56+
begin
57+
58+
requests_int <= unsigned(requests);
59+
60+
round_robin_mode : if mode = ROUND_ROBIN generate
61+
-- This uses a grant-masking scheme to generate round-robin grant behavior.
62+
-- We want to mask off the previous granted channel and any lower bits
63+
-- so the upper bits get a round-robin chance.
64+
grants_mask <= not (grants_last or (grants_last - 1));
65+
66+
-- Mask the requests based on the current grant mask, unless we have no active requests or grants, in
67+
-- which case, pass the unmasked vector through
68+
requests_masked <= requests_int and grants_mask when (requests_int and grants_mask) /= 0 else
69+
requests_int;
70+
else generate
71+
-- In priority mode, we needn't mask grants since the priority encoder takes over
72+
-- and we will allow multiple grants to the same requester to the exclusion of others
73+
-- given the desired priority.
74+
grants_mask <= (others => '0');
75+
requests_masked <= requests_int;
76+
end generate;
77+
78+
-- Build two's complement, remember basic boolean math? 2's complement = (not <dat>) + 1
79+
requests_masked_twos <= (not requests_masked) + 1;
80+
81+
fedge_detects : for i in requests_int'range generate
82+
req_vec_f_edge(i) <= '1' when requests_int(i) = '0' and requests_last(i) = '1' else
83+
'0';
84+
end generate;
85+
86+
-- Unary OR reduction, active when any bit is active
87+
req_f_edge <= or req_vec_f_edge;
88+
89+
the_arbiter : process (clk)
90+
begin
91+
if reset then
92+
grants_int <= zeros;
93+
grants_last <= (others => '0');
94+
requests_last <= (others => '0');
95+
elsif rising_edge(clk) then
96+
-- Store history for edge detector
97+
requests_last <= requests_int;
98+
-- To determine a grant, we take the currently active requests vector,
99+
-- which is masked by the allowable requests in round-robbin mode, and then
100+
-- bitwise AND that with it's two's complement
101+
-- to get 1 bit active as our active grant.
102+
grants_int <= requests_masked and requests_masked_twos;
103+
if req_f_edge then
104+
-- Note: we expect requesters of this to hold request high until they both have the grant,
105+
-- and are finished with their current transaction. This means that falling edges of
106+
-- requests cause arbitration updates and we save the current grant for use in round-robin
107+
-- arbitration next time.
108+
grants_last <= grants_int;
109+
end if;
110+
end if;
111+
end process;
112+
113+
grants <= std_logic_vector(grants_int);
114+
115+
end rtl;

hdl/ip/vhd/arb_mux_demux/arbiter_pkg.vhd

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
--
55
-- Copyright 2024 Oxide Computer Company
66

7-
87
--! Common shared information for arbiters
98
package arbiter_pkg is
109

11-
type arbiter_mode is (PRIORITY, ROUND_ROBIN);
10+
type arbiter_mode is (priority, round_robin);
1211

13-
end package;
12+
end package;

hdl/ip/vhd/arb_mux_demux/sims/arbiter_sim_pkg.vhd

+24-18
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,52 @@ use ieee.std_logic_1164.all;
99
use ieee.numeric_std.all;
1010

1111
library vunit_lib;
12-
context vunit_lib.vunit_context;
13-
context vunit_lib.com_context;
14-
12+
context vunit_lib.vunit_context;
13+
context vunit_lib.com_context;
1514
use work.gpio_msg_pkg.all;
1615

1716
package arbiter_sim_pkg is
1817

19-
procedure set_arb(
20-
signal net : inout network_t;
18+
procedure set_arb (
19+
signal net : inout network_t;
2120
variable msg_target :in actor_t;
22-
variable data: in std_logic_vector
21+
variable data : in std_logic_vector
2322
);
24-
procedure get_grant(
25-
signal net : inout network_t;
23+
24+
procedure get_grant (
25+
signal net : inout network_t;
2626
variable msg_target :in actor_t;
27-
variable data: out std_logic_vector
27+
variable data : out std_logic_vector
2828
);
2929

3030
end package;
3131

3232
package body arbiter_sim_pkg is
3333

34-
procedure set_arb(
35-
signal net : inout network_t;
34+
procedure set_arb (
35+
signal net : inout network_t;
3636
variable msg_target :in actor_t;
37-
variable data: in std_logic_vector
37+
variable data : in std_logic_vector
3838
) is
39-
variable send_data: std_logic_vector(GPIO_MESAGE_DATA_WDITH - 1 downto 0) := (others => '0');
39+
40+
variable send_data : std_logic_vector(GPIO_MESAGE_DATA_WDITH - 1 downto 0) := (others => '0');
41+
4042
begin
4143
send_data(data'range) := data;
4244
set_gpio(net, msg_target, send_data);
4345
end;
44-
procedure get_grant(
45-
signal net : inout network_t;
46+
47+
procedure get_grant (
48+
signal net : inout network_t;
4649
variable msg_target :in actor_t;
47-
variable data: out std_logic_vector
50+
variable data : out std_logic_vector
4851
) is
49-
variable get_data: std_logic_vector(GPIO_MESAGE_DATA_WDITH - 1 downto 0) := (others => '0');
52+
53+
variable get_data : std_logic_vector(GPIO_MESAGE_DATA_WDITH - 1 downto 0) := (others => '0');
54+
5055
begin
5156
get_gpio(net, msg_target, get_data);
5257
data := get_data(data'range);
5358
end;
54-
end package body;
59+
60+
end package body;

0 commit comments

Comments
 (0)