Skip to content

High quality and composable base RTL libraries in Verilog

License

Notifications You must be signed in to change notification settings

xlsynth/bedrock-rtl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bedrock-RTL

Warning
UNDER CONSTRUCTION. Everything is broken.

High quality and composable base RTL libraries in Verilog

Prerequisites

You need to have the following tools installed in your environment.

  • Bazel (tested with 7.3.1)

  • pre-commit (tested with 3.8.0)

  • Your own EDA tools (for running tests)

TODO(mgottscho): Add more as we implement more things.

Pre-Commit Hooks

We use pre-commit hooks to enforce code quality. 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

Building and Testing

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 they call a placeholder wrapper script that does not reference any particular vendor EDA tool. We do this because:

  1. We want to keep test definitions as vendor-agnostic as possible.

  2. Certain vendors may have non-disclosure agreements that protect usage of their APIs or licensing agreements that restrict where and how the tools can be run.

You will need to point Bazel to a "real" implementation of the wrapper script to be able to run the tests.

The Bazel test rule implementations at //bazel:verilog.bzl shell out to a program with a generic EDA vendor tool-agnostic API that actually implements the test. By default, a placeholder tool called placeholder_verilog_runner.py is used. It implements the argument parsing part of the API but does nothing other than fail the test. This placeholder test is generated by Bazel during the build with //bazel:write_placeholder_verilog_runner_py.bzl.

To use a real implementation of the script, you tell Bazel where to find it by setting --action_env=BAZEL_VERILOG_RUNNER_TOOL=/path/to/your/verilog_runner.py on the command line or in the .bazelrc file.

Continuous Integration

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.

Style Guide

We follow the xlsynth Verilog Style Guide, which is a fork of the lowRISC style guide with some minor differences.

Bazel Rules for Verilog

This repository defines several generally-helpful Bazel Verilog rules that you can use in your own projects.

verilog_library (external)

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"],
)

Other rules

Please see bazel/verilog_rules.md for documentation on rules defined in this repository.

Using Bedrock

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"],
)

macros: Macros and Defines

br_registers.svh: Flip-Flop Inference Macros

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, then clk and either rst if synchronous or arst if asynchronous)

Important
Clocks are always positive-edge triggered. Resets are always active-high.
Macro/define Description Implemented Tested

BR_REGA

Flip-flop register with unconditional load, asynchronous active-high reset named arst, initial value 0, positive-edge triggered clock named clk.

Yes

Yes

BR_REGAIL

Flip-flop register with conditional load enable, asynchronous active-high reset named arst, initial value given, positive-edge triggered clock named clk.

Yes

Yes

BR_REGAI

Flip-flop register with unconditional load, asynchronous active-high reset named arst, initial value given, positive-edge triggered clock named clk.

Yes

Yes

BR_REGAL

Flip-flop register with conditional load enable, asynchronous active-high reset named arst, initial value 0, positive-edge triggered clock named clk.

Yes

Yes

BR_REGIL

Flip-flop register with conditional load enable, synchronous active-high reset named rst, initial value given, positive-edge triggered clock named clk.

Yes

Yes

BR_REGI

Flip-flop register with unconditional load, synchronous active-high reset named rst, initial value given, positive-edge triggered clock named clk.

Yes

Yes

BR_REGILX

Flip-flop register with conditional load enable, synchronous active-high given reset, initial value given, positive-edge triggered given clock.

Yes

Yes

BR_REGIX

Flip-flop register with unconditional load, synchronous active-high given reset, initial value given, positive-edge triggered given clock.

Yes

Yes

BR_REGLN

Flip-flop register with load enable, no reset, positive-edge triggered clock named clk.

Yes

Yes

BR_REGLX

Flip-flop register with conditional load enable, synchronous active-high reset, initial value 0, positive-edge triggered given clock.

Yes

Yes

BR_REGL

Flip-flop register with conditional load enable, synchronous active-high reset named rst, initial value 0, positive-edge triggered clock named clk.

Yes

Yes

BR_REGN

Flip-flop register with unconditional load, no reset, positive-edge triggered clock named clk.

Yes

Yes

BR_REGX

Flip-flop register with unconditional load, synchronous active-high given reset, initial value 0, positive-edge triggered given clock.

Yes

Yes

BR_REG

Flip-flop register with unconditional load, synchronous active-high reset named rst, initial value 0, positive-edge triggered clock named clk.

Yes

Yes

br_asserts.svh: Public Assertions

These assertion macros are intended for use by the user in their own designs. They are guarded (enabled) by the following defines:

  • ifdef BR_ASSERT_ON

  • ifdef BR_ENABLE_ASSERT_COMB - only for guarding BR_ASSERT_COMB (off by default).

Important
Clocks are always positive-edge triggered. Resets are always active-high.
Macro/define Description Implemented Tested

BR_ASSERT_STATIC

Static (elaboration-time) assertion for use within modules

Yes

Yes

BR_ASSERT_STATIC_IN_PACKAGE

Static (elaboration-time) assertion for use within packages

Yes

Yes

BR_ASSERT

Concurrent assertion with implicit clk and rst names.

Yes

Yes

BR_ASSERT_CR

Concurrent assertion with explicit clock and reset names.

Yes

Yes

BR_ASSERT_COMB

Combinational/immediate assertion. Also passes if the expression is unknown. Enable by defining BR_ENABLE_ASSERT_COMB.

Yes

Yes

BR_COVER

Concurrent cover with implicit clk and rst names.

Yes

Yes

BR_COVER_CR

Concurrent cover with explicit clock and reset names.

Yes

Yes

BR_COVER_COMB

Combinational/immediate cover.

Yes

Yes

BR_ASSUME

Concurrent assumption with implicit clk and rst names.

Yes

Yes

BR_ASSUME_CR

Concurrent assumption with explicit clock and reset names.

Yes

Yes

br_asserts_internal.svh: Bedrock-internal Assertions

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:

  • ifndef BR_DISABLE_INTG_CHECKS for the integration cases

  • ifdef BR_ENABLE_IMPL_CHECKS for the implementation cases

Macro/define Description Implemented Tested

BR_ASSERT_INTG

Concurrent integration assertion with implicit clk and rst names. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_ASSERT_CR_INTG

Concurrent integration assertion with explicit clock and reset names. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_ASSERT_IMPL

Concurrent implementation assertion with implicit clk and rst names. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

BR_ASSERT_CR_IMPL

Concurrent implementation assertion with explicit clock and reset names. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

BR_ASSERT_COMB_INTG

Combinational/immediate integration assertion. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_ASSERT_COMB_IMPL

Combinational/immediate implementation assertion. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

BR_COVER_INTG

Concurrent integration cover with implicit clk and rst names. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_COVER_CR_INTG

Concurrent integration cover with explicit clock and reset names. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_COVER_IMPL

Concurrent implementation cover with implicit clk and rst names. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

BR_COVER_CR_IMPL

Concurrent implementation cover with explicit clock and reset names. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

BR_COVER_COMB_INTG

Combinational/immediate integration cover. Disable by defining BR_DISABLE_INTG_CHECKS.

Yes

Yes

BR_COVER_COMB_IMPL

Combinational/immediate implementation cover. Enable by defining BR_ENABLE_IMPL_CHECKS.

Yes

Yes

br_gates.svh: Gate Convenience Wrappers

These macros conveniently wrap module instantiations from the gate category.

Macro/define Description Implemented Tested

BR_GATE_BUF

Instantiates br_gate_buf.

Yes

Yes

BR_GATE_CLK_BUF

Instantiates br_gate_clk_buf.

Yes

Yes

BR_GATE_INV

Instantiates br_gate_inv.

Yes

Yes

BR_GATE_AND2

Instantiates br_gate_and2.

Yes

Yes

BR_GATE_OR2

Instantiates br_gate_or2.

Yes

Yes

BR_GATE_XOR2

Instantiates br_gate_xor2.

Yes

Yes

BR_GATE_MUX2

Instantiates br_gate_mux2.

Yes

Yes

BR_GATE_CLK_MUX2

Instantiates br_gate_clk_mux2.

Yes

Yes

BR_GATE_ICG

Instantiates br_gate_icg.

Yes

Yes

br_tieoff.svh: Tie-off Convenience Wrappers

These macros conveniently wrap br_misc_tieoff* module instantiations.

Macro/define Description Implemented Tested

BR_TIEOFF_ZERO_NAMED

Instantiates br_tieoff_zero with a given submodule instance suffix.

Yes

Yes

BR_TIEOFF_ONE_NAMED

Instantiates br_tieoff_one with a given submodule instance suffix.

Yes

Yes

BR_TIEOFF_ZERO

Instantiates br_tieoff_zero with a derived submodule instance suffix.

Yes

Yes

BR_TIEOFF_ONE

Instantiates br_tieoff_one with a derived submodule instance suffix.

Yes

Yes

BR_TIEOFF_ZERO_TODO

Provided for convenience of the user grepping for TODO in the codebase, to help prevent accidental tie-offs that result in bugs. Instantiates br_tieoff_zero with a derived submodule instance suffix.

Yes

Yes

BR_TIEOFF_ONE_TODO

Provided for convenience of the user grepping for TODO in the codebase, to help prevent accidental tie-offs that result in bugs. Instantiates br_tieoff_one with a derived submodule instance suffix.

Yes

Yes

br_unused.svh: Unused Signal Convenience Wrappers

These macros conveniently wrap br_misc_unused module instantiations.

Macro/define Description Implemented Tested

BR_UNUSED_NAMED

Instantiates br_misc_unused with a given submodule instance suffix.

Yes

Yes

BR_UNUSED

Instantiates br_misc_unused with a derived submodule instance suffix.

Yes

Yes

BR_UNUSED_TODO

Provided for convenience of the user grepping for TODO in the codebase, to help prevent accidental unused signals that result in bugs. Instantiates br_misc_unused with a derived submodule instance suffix.

Yes

Yes

Modules

arb: Arbiters

Module Description Implemented Verified

br_arb_fixed

Fixed priority

Yes

br_arb_lru

Least-recently used

Yes

br_arb_rr

Round-robin

Yes

cdc: Clock Domain Crossings

Module Description Implemented Verified

br_cdc_bit

Single-bit CDC

br_cdc_fifo_ctrl_1r1w

Bus CDC using a dual-clock FIFO controller for a 1R1W dual-clock SRAM

  • Push flow control: ready/valid

  • Pop flow control: ready/valid

br_cdc_fifo_flops

Bus CDC using a dual-clock FIFO with internal flop-RAM

  • Push flow control: ready/valid

  • Pop flow control: ready/valid

counter: Wrapping and Saturating Counters

Module Description Implemented Verified

br_counter_decr

Decrementing counter

Yes

br_counter_incr

Incrementing counter

Yes

br_counter_sat

Up-down saturating counter

br_counter

Up-down counter

Yes

credit: Credit/Valid Flow Control

Module Description Implemented Verified

br_credit_counter

Credit counter

Yes

br_credit_receiver

Credit/valid to ready/valid converter (credit-loop receiver-side)

Yes

br_credit_sender

Ready/valid to credit/valid converter (credit-loop sender-side)

Yes

delay: Fixed-Delay Pipelines

Module Description Implemented Verified

br_delay

With reset

Yes

br_delay_nr

Without reset

Yes, but want to merge with br_delay (#137)

br_delay_valid_next_nr

With self-gating (valid-next) and without reset

Yes, but want to merge with br_delay_valid_next (#137)

br_delay_valid_next

With self-gating (valid-next)

Yes

br_delay_valid

With self-gating (valid)

Yes

demux: Simple Demultiplexers

Module Description Implemented Verified

br_demux_onehot

One-hot demultiplexer

Yes

br_demux_bin

Binary-select demultiplexer

Yes

enc: Combinational encoders

Module Description Implemented Verified

br_enc_bin2gray

Binary to gray

Yes

br_enc_bin2onehot

Binary to onehot

Yes

br_enc_gray2bin

Gray to binary

Yes

br_enc_onehot2bin

One-hot to binary

Yes

br_enc_priority_encoder

Priority encoder

Yes

ecc: Error Correcting Codes

Module Description Implemented Verified

br_ecc_secded_decoder

Single-error-correcting, double-error-detecting (SECDED) decoder

br_ecc_secded_encoder

Single-error-correcting, double-error-detecting (SECDED) encoder

br_ecc_sed_decoder

Single-error-detecting (SED) decoder

Yes

br_ecc_sed_encoder

Single-error-detecting (SED) encoder

Yes

fifo: First-In-First-Out Queues

Module Description Implemented Verified

br_fifo_ctrl_1r1w_bare

FIFO controller with external RAM port for 1R1W

  • Push flow control: none

  • Pop flow control: none

br_fifo_ctrl_1r1w_pop_credit

FIFO controller with external RAM port for 1R1W

  • Push flow control: ready/valid

  • Pop flow control: credit/valid

br_fifo_ctrl_1r1w_push_credit

FIFO controller with external RAM port for 1R1W

  • Push flow control: credit/valid

  • Pop flow control: ready/valid

Yes

br_fifo_ctrl_1r1w

FIFO controller with external RAM port for 1R1W

  • Push flow control: ready/valid

  • Pop flow control: ready/valid

Yes

br_fifo_flops_pop_credit

FIFO with internal flop RAM

  • Push flow control: ready/valid

  • Pop flow control: credit/valid

br_fifo_flops_push_credit

FIFO with internal flop RAM

  • Push flow control: credit/valid

  • Pop flow control: ready/valid

Yes

br_fifo_flops

FIFO with internal flop RAM

  • Push flow control: ready/valid

  • Pop flow control: ready/valid

Yes

flow: Ready/Valid Flow Control

Module Description Implemented Verified

br_flow_arb_fixed

Fixed priority arbiter

Yes

br_flow_arb_lru

Least-recently used arbiter

Yes

br_flow_arb_rr

Round-robin arbiter

Yes

br_flow_demux_select

Registered demultiplexer, external select

Yes

br_flow_demux_select_unstable

Combinational demultiplexer, external select, with unstable flow control

Yes

br_flow_fork

Datapath flow control split

Yes

br_flow_join

Datapath flow control join

Yes

br_flow_mux_fixed

Arbitrated multiplexer, fixed priority

Yes

br_flow_mux_lru

Arbitrated multiplexer, least-recently used

Yes

br_flow_mux_rr

Arbitrated multiplexer, round-robin

Yes

br_flow_mux_select

Registered multiplexer, user select

Yes

br_flow_mux_select_unstable

Combinational multiplexer, external select, with unstable flow control

Yes

br_flow_reg_both

Pipeline register, registered forward and reverse signals

Yes

br_flow_reg_fwd

Pipeline register, registered forward signals

Yes

br_flow_reg_rev

Pipeline register, registered backward signals

Yes

gate: Behavioral Gate Primitives

Module Description Implemented Verified

br_gate_buf

Wire buffer/repeater

Yes

br_gate_clk_buf

Clock wire buffer/repeater

Yes

br_gate_inv

Inverter

Yes

br_gate_and2

Two-input AND gate

Yes

br_gate_or2

Two-input OR gate

Yes

br_gate_xor2

Two-input XOR gate

Yes

br_gate_mux2

Two-input multiplexer

Yes

br_gate_clk_mux2

Two-input clock multiplexer

Yes

br_gate_icg

Integrated clock gate

Yes

misc: Miscellaneous

Module Description Implemented Verified

br_misc_tieoff_one

Drive an expression to constant 1s and internally waive relevant lint rules

Yes

Yes

br_misc_tieoff_zero

Drive an expression to constant 0s and internally waive relevant lint rules

Yes

Yes

br_misc_unused

Sink an unused expression and internally waive relevant lint rules

Yes

Yes

mux: Simple Multiplexers

Module Description Implemented Verified

br_mux_onehot

One-hot multiplexer

Yes

br_mux_bin

Binary-select multiplexer

Yes

ram: Memories

Module Description Implemented Verified

br_ram_addr_decoder_tree

Address decoder tree for a tiled RAM

WIP

br_ram_addr_decoder

Address decoder for a tiled RAM

Yes

br_ram_flops_1r1w_tile

One-tile flop-RAM with one read port and one write port

Yes

br_ram_flops_1r1w

Tiled flop-RAM with one read port and one write port

Yes

br_ram_flops_1rw_tile

One-tile flop-RAM with one port (shared for read and write)

br_ram_flops_1rw

Tiled flop-RAM with one port (shared for read and write)

br_ram_data_rd_pipe

Pipeline for reading data from a tiled RAM

Yes

timer: Saturating and Wrapping Timers

Module Description Implemented Verified

br_timer_sat

Tick down from a threshold and saturate at zero; signal continuously at zero

br_timer

Tick down from a threshold and signal a pulse every time when wrapping past zero

Packages

br_math: Non-synthesizable Math Helper Functions

Function Description Implemented Tested

ceil_div

Return integer ceiling division

Yes

Yes

floor_div

Return integer floor division

Yes

Yes

clogb

Return integer ceiling of base-b logarithm where b is a power-of-2

Yes

Yes

is_power_of_2

Return 1 if an integer is a power of 2

Yes

Yes

is_even

Return 1 if an integer is even

Yes

Yes

About

High quality and composable base RTL libraries in Verilog

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published