Warning
|
UNDER CONSTRUCTION. Many things are broken. |
High quality and composable base RTL libraries in Verilog
At minimum, you need to have the following tools installed in your environment.
-
Bazel (tested with 7.3.1)
-
System Python interpreter (tested with 3.12.5)
You can use the provided Dockerfile to build a container image with the above dependencies installed. For example:
docker build . --target user --tag=bedrock-rtl:${USER}
docker run -v $(pwd):/src -w /src bedrock-rtl:${USER} <YOUR_COMMAND>
You need to provide your own EDA tool plugins that implement the plugin API for verilog_runner.py
.
TODO: Add support for open-source EDA tools. iverilog would be nice but it does not support macros with arguments.
We use pre-commit hooks to enforce basic coding style. To install the hooks, run:
pre-commit install
They should automatically run on every commit. You can also run them manually via:
pre-commit run
We’ve tested with pre-commit version 4.0.1.
We use the powerful Bazel build system to assemble filelists and to run all tests (elaboration, lint, simulation, and formal).
A one-step command builds and runs all tests:
bazel test //...
Important
|
Action required for tests to pass!
By default, the Bazel tests will fail because the repository does not currently provide any EDA tool plugins for the
You will need to implement the plugin API by subclassing |
The Bazel test rule implementations at //bazel:verilog.bzl
shell out the //python/verilog_runner/verilog_runner.py
tool that presents a generic tool-agnostic API that actually implements the test.
Using GitHub Actions, which currently just runs pre-commit checks.
TODO(mgottscho): Find a way to have CI run Bazel tests using real EDA tools.
We follow the xlsynth Verilog Style Guide, which is a fork of the lowRISC style guide with some minor differences.
This repository defines several generally-helpful Bazel Verilog rules that you can use in your own projects.
The verilog_library
rule is used to collect Verilog source and header files and track their dependencies.
The original definition of the verilog_library
rule can be found here.
We pick up that rule dependency transitively (see the top-level MODULE.bazel
).
Using verilog_library
load("@rules_hdl//verilog:providers.bzl", "verilog_library")
verilog_library(
name = "bar",
srcs = ["bar.sv"],
hdrs = ["baz.svh"]
)
verilog_library(
name = "foo",
srcs = ["foo.sv"],
deps = [":bar"],
)
Please see bazel/verilog_rules.md for documentation on rules defined in this repository.
Usage is best illustrated with an example using the bzlmod dependency management system in Bazel.
Tip
|
You are not required to use Bazel to depend on Bedrock-RTL. You can also use the Verilog files directly in your own projects (e.g., with git submodule, git subtree, or some other method). |
In your project’s MODULE.bazel
:
MODULE.bazel
module(name = "your-project")
bazel_dep(name = "bedrock-rtl", version = "0.0.1")
git_override(
module_name = "bedrock-rtl",
commit = <fill_in_git_commit_sha>,
remote = "https://github.com/xlsynth/bedrock-rtl",
)
rules_hdl_extension = use_extension("@bedrock-rtl//dependency_support/rules_hdl:extension.bzl", "rules_hdl_extension")
use_repo(rules_hdl_extension, "rules_hdl")
Then suppose you have the following SystemVerilog module called datapath_join.sv
:
datapath_join.sv
// An example design using two Bedrock-RTL modules: br_flow_reg_fwd and br_flow_join.
//
// Joins two or more equal-width datapaths into a single output datapath.
// Uses ready/valid protocol on all flows.
// Push-side is registered.
`include "br_asserts.svh"
module datapath_join #(
parameter int NumFlows = 2, // must be at least 2
parameter int WidthPerFlow = 32 // must be at least 1
) (
input logic clk,
input logic rst,
output logic [NumFlows-1:0] push_ready,
input logic [NumFlows-1:0] push_valid,
input logic [NumFlows-1:0][WidthPerFlow-1:0] push_data,
input logic pop_ready,
output logic pop_valid,
output logic [(NumFlows*WidthPerFlow)-1:0] pop_data
);
`BR_ASSERT_STATIC(numflows_gte_2_a, NumFlows >= 2)
`BR_ASSERT_STATIC(widthperflow_gte_1_a, WidthPerFlow >= 1)
logic [NumFlows-1:0] inter_ready;
logic [NumFlows-1:0] inter_valid;
logic [NumFlows-1:0][WidthPerFlow-1:0] inter_data;
for (genvar i = 0; i < NumFlows; i++) begin : gen_regs
br_flow_reg_fwd #(
.Width(WidthPerFlow)
) br_flow_reg_fwd (
.clk,
.rst,
.push_ready(push_ready[i]),
.push_valid(push_valid[i]),
.push_data (push_data[i]),
.pop_ready (inter_ready[i]),
.pop_valid (inter_valid[i]),
.pop_data (inter_data[i])
);
end
br_flow_join #(
.NumFlows(NumFlows)
) br_flow_join (
.clk,
.rst,
.push_ready(inter_ready),
.push_valid(inter_valid),
.pop_ready (pop_ready),
.pop_valid (pop_valid)
);
assign pop_data = inter_data; // direct concat
endmodule : datapath_join
Your BUILD.bazel
file could then do this:
BUILD.bazel
load("@bedrock-rtl//bazel:verilog.bzl", "verilog_elab_and_lint_test_suite", "verilog_elab_test", "verilog_lint_test")
load("@rules_hdl//verilog:providers.bzl", "verilog_library")
package(default_visibility = ["//visibility:private"])
verilog_library(
name = "datapath_join",
srcs = ["datapath_join.sv"],
deps = [
"@bedrock-rtl//flow/rtl:br_flow_join",
"@bedrock-rtl//flow/rtl:br_flow_reg_fwd",
"@bedrock-rtl//macros:br_asserts",
],
)
verilog_elab_test(
name = "datapath_join_elab_test",
deps = [":datapath_join"],
)
verilog_lint_test(
name = "datapath_join_lint_test",
deps = [":datapath_join"],
)
verilog_elab_and_lint_test_suite(
name = "datapath_join_test_suite",
params = {
"NumFlows": [
"2",
"3",
],
"WidthPerFlow": [
"1",
"64",
],
},
deps = [":datapath_join"],
)
Some test code in this repository was written and debugged with the assistance of tools by ChipStack.ai.
The relevant code is located in subdirectories named accordingly (e.g., arb/sim/chipstack/
).
The copyright is still held by the Bedrock-RTL authors and licensed the same as the rest of the code in this repository.
Refer to the LICENSE
file.
These macros conveniently wrap always_ff
blocks, improving readability and helping to structure user code into sequential and combinational portions.
The macros are named according to the following suffix convention.
-
A
: Asynchronous reset (if absent, then synchronous) -
I
: Initial value given (if absent, then 0) -
L
: Conditional load enable (if absent, then unconditional) -
N
: No reset (if absent, then reset) -
X
: Given explicit clock and reset names (if absent, thenclk
and eitherrst
if synchronous orarst
if asynchronous)
Important
|
Clocks are always positive-edge triggered. Resets are always active-high. |
Note
|
The order of the suffices generally matches the order of the arguments to the macro.
The suffices are also listed in alphabetical order, with the exception of L before I .
|
Macro/define | Description | Implemented | Tested |
---|---|---|---|
|
Flip-flop register with unconditional load, asynchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with conditional load enable, asynchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with unconditional load, asynchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with conditional load enable, asynchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with conditional load enable, synchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with unconditional load, synchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with conditional load enable, synchronous active-high given reset, initial value given, positive-edge triggered given clock. |
Yes |
Yes |
|
Flip-flop register with unconditional load, synchronous active-high given reset, initial value given, positive-edge triggered given clock. |
Yes |
Yes |
|
Flip-flop register with load enable, no reset, positive-edge triggered clock named |
Yes |
Yes |
|
Flip-flop register with conditional load enable, synchronous active-high reset, initial value 0, positive-edge triggered given clock. |
Yes |
Yes |
|
Flip-flop register with conditional load enable, synchronous active-high reset named |
Yes |
Yes |
|
Flip-flop register with unconditional load, no reset, positive-edge triggered clock named |
Yes |
Yes |
|
Flip-flop register with unconditional load, synchronous active-high given reset, initial value 0, positive-edge triggered given clock. |
Yes |
Yes |
|
Flip-flop register with unconditional load, synchronous active-high reset named |
Yes |
Yes |
These assertion macros are intended for use by the user in their own designs. They are guarded (enabled) by the following defines:
-
BR_ASSERT_ON
 — if not defined, then all macros other thanBR_ASSERT_STATIC*
are no-ops. -
BR_ENABLE_FPV
 — if not defined, then allBR_*_FPV
macros are no-ops. -
BR_DISABLE_ASSERT_IMM
 — if defined, then allBR_ASSERT_IMM*
,BR_COVER_IMM*
,BR_ASSERT_COMB*
, andBR_ASSERT_IMM*
macros are no-ops. -
BR_DISABLE_FINAL_CHECKS
 — if defined, then allBR_ASSERT_FINAL*
macros are no-ops.
Tip
|
It is recommended that users simply define BR_ASSERT_ON when integrating Bedrock modules into their designs.
The other guards will typically not be necessary.
|
Important
|
Clocks are always positive-edge triggered. Resets are always active-high. |
Macro/define | Description |
---|---|
|
Static (elaboration-time) assertion for use within modules |
|
Static (elaboration-time) assertion for use within packages |
|
Immediate assertion evaluated at the end of simulation (e.g., when |
|
Concurrent assertion with implicit |
|
Concurrent assertion with explicit clock and reset names. |
|
Immediate assertion.
Also passes if the expression is unknown.
Disable by defining |
|
Immediate assertion wrapped inside of an |
|
Concurrent cover with implicit |
|
Concurrent cover with explicit clock and reset names. |
|
Immediate cover.
Disable by defining |
|
Immediate cover wrapped inside of an |
|
Concurrent assumption with implicit |
|
Concurrent assumption with explicit clock and reset names. |
|
Concurrent assertion that is active in reset and out of reset
(but specifically intended for checking the former), with implicit |
|
Concurrent assertion that is active in reset and out of reset (but specifically intended for checking the former), with explicit clock name. |
These assertion macros are intended for use in formal verification monitors that might be integrated into a simulation environment, but where not all formal assertions should be used in simulation. They are guarded (enabled) by the following defines:
-
BR_ENABLE_FPV
 — if not defined, then all BR_*_FPV macros are no-ops.
Macro/define | Description |
---|---|
|
Wraps BR_ASSERT. |
|
Wraps BR_ASSERT_CR. |
|
Wraps BR_ASSERT_COMB. |
|
Wraps BR_COVER. |
|
Wraps BR_COVER_CR. |
|
Wraps BR_COVER_COMB. |
|
Wraps BR_ASSUME. |
|
Wraps BR_ASSUME_CR. |
These assertion macros wrap the public assertions. They are intended only for internal use inside Bedrock libraries, but the user needs to know about them. They are guarded (enabled) by the following defines:
The macros in this file are guarded with the following defines.
* BR_DISABLE_INTG_CHECKS
 — if defined, then all the BR_*INTG checks are no-ops.
* BR_ENABLE_IMPL_CHECKS
 — if not defined, then all the BR*_IMPL checks are no-ops.
The intent is that users should not need to do anything, so that by default they will get only the integration checks but not the implementation checks.
Tip
|
All of these macros wrap the public macros in br_asserts.svh , so they are also subject to the same global defines such as BR_ASSERT_ON .
|
These checks are meant for checking the integration of a library module into an end user’s design.
Disable them globally by defining BR_DISABLE_INTG_CHECKS
.
Macro/define | Description |
---|---|
|
Wraps BR_ASSERT. |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
These checks are meant for checking the implementation of a library module.
Enable them globally by defining BR_ENABLE_IMPL_CHECKS
.
Macro/define | Description |
---|---|
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
|
Wraps |
These macros conveniently wrap module instantiations from the gate
category.
Macro/define | Description |
---|---|
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
These macros conveniently wrap br_misc_tieoff*
module instantiations.
Macro/define | Description |
---|---|
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Instantiates |
|
Provided for convenience of the user grepping for |
|
Provided for convenience of the user grepping for |
These macros conveniently wrap br_misc_unused
module instantiations.
Macro/define | Description |
---|---|
|
Instantiates |
|
Instantiates |
|
Provided for convenience of the user grepping for |
Module | Description | Verified |
---|---|---|
|
Fixed priority |
Yes |
|
Least-recently used |
Yes |
|
Round-robin |
Yes |
Module | Description | Verified |
---|---|---|
|
Single-bit toggle CDC |
|
|
Bus CDC using a dual-clock FIFO controller for a 1R1W dual-clock SRAM
|
|
|
Bus CDC using a dual-clock FIFO controller for a 1R1W dual-clock SRAM
|
|
|
Bus CDC using a dual-clock FIFO with internal flop-RAM
|
|
|
Bus CDC using a dual-clock FIFO with internal flop-RAM
|
Module | Description | Verified |
---|---|---|
|
Decrementing counter |
|
|
Incrementing counter |
|
|
Up-down counter |
Module | Description | Verified |
---|---|---|
|
Credit counter |
|
|
Credit/valid to ready/valid converter (credit-loop receiver-side) |
|
|
Ready/valid to credit/valid converter (credit-loop sender-side) |
Module | Description | Verified |
---|---|---|
|
Without reset |
|
|
Loadable shift register |
|
|
With reset |
|
|
With self-gating (valid-next) and without reset |
|
|
With self-gating (valid-next) |
|
|
With self-gating (valid) and without reset |
|
|
With self-gating (valid) |
Module | Description | Verified |
---|---|---|
|
One-hot demultiplexer |
|
|
Binary-select demultiplexer |
Module | Description | Verified |
---|---|---|
|
Binary to gray |
|
|
Binary to onehot |
|
|
Count the number of ones in a vector |
|
|
Gray to binary |
|
|
One-hot to binary |
|
|
Priority encoder |
Module | Description | Verified |
---|---|---|
|
Single-error-correcting, double-error-detecting (SECDED) decoder |
|
|
Single-error-correcting, double-error-detecting (SECDED) encoder |
|
|
Single-error-detecting (SED) decoder |
|
|
Single-error-detecting (SED) encoder |
Module | Description | Verified |
---|---|---|
|
FIFO controller with external RAM port for 1R1W
|
|
|
FIFO controller with external RAM port for 1R1W
|
|
|
FIFO with internal flop RAM
|
|
|
FIFO with internal flop RAM
|
Module | Description | Verified |
---|---|---|
|
Fixed priority arbiter |
|
|
Least-recently used arbiter |
|
|
Round-robin arbiter |
|
|
Registered demultiplexer, external select |
|
|
Combinational demultiplexer, external select, with unstable flow control |
|
|
Deserialize a packet from a many narrow flits to fewer wide flits |
|
|
Datapath flow control split |
|
|
Datapath flow control join |
|
|
Arbitrated multiplexer, fixed priority |
|
|
Arbitrated multiplexer, least-recently used |
|
|
Arbitrated multiplexer, round-robin |
|
|
Registered multiplexer, user select |
|
|
Combinational multiplexer, external select, with unstable flow control |
|
|
Pipeline register, registered forward and reverse signals |
|
|
Pipeline register, registered forward signals |
|
|
Pipeline register, registered backward signals |
|
|
Serialize a packet from a few wide flits to many narrow flits |
Module | Description |
---|---|
|
Wire buffer/repeater |
|
Clock wire buffer/repeater |
|
Inverter |
|
Two-input AND gate |
|
Two-input OR gate |
|
Two-input XOR gate |
|
Two-input multiplexer |
|
Two-input clock multiplexer |
|
Integrated clock gate |
|
Integrated clock gate with synchronous reset |
|
Clock domain crossing synchronizer cell |
|
Buffer for clock domain crossings of pseudo-static nets |
|
Buffer for clock domain crossings that indicate a given net should be checked for max delay (skew) |
Module | Description | Implemented | Verified |
---|---|---|---|
|
Drive an expression to constant 1s and internally waive relevant lint rules |
Yes |
Yes |
|
Drive an expression to constant 0s and internally waive relevant lint rules |
Yes |
Yes |
|
Sink an unused expression and internally waive relevant lint rules |
Yes |
Yes |
Module | Description | Implemented | Verified |
---|---|---|---|
|
One-hot multiplexer |
Yes |
|
|
Binary-select multiplexer |
Yes |
Module | Description | Verified |
---|---|---|
|
Address decoder and optional write data steering for a tiled RAM |
|
|
Pipeline for reading data from a tiled RAM |
|
|
Simplified version of |
|
|
Tiled flop-RAM with one or more read ports and one or more write ports |
|
|
One-tile flop-RAM with one or more read ports and one or more write ports |
Function | Description | Implemented | Tested |
---|---|---|---|
|
Return integer ceiling division |
Yes |
Yes |
|
Return integer floor division |
Yes |
Yes |
|
Return integer ceiling of base- |
Yes |
Yes |
|
Return 1 if an integer is a power of 2 |
Yes |
Yes |
|
Return 1 if an integer is even |
Yes |
Yes |