Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions cdc/rtl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,37 @@ br_verilog_elab_and_lint_test_suite(
"//gate/rtl:br_gate_mock",
],
)

verilog_library(
name = "br_cdc_stable_data_autoupdate",
srcs = ["br_cdc_stable_data_autoupdate.sv"],
deps = [
":br_cdc_stable_data",
"//macros:br_asserts_internal",
"//macros:br_registers",
],
)

br_verilog_elab_and_lint_test_suite(
name = "br_cdc_stable_data_autoupdate_test_suite",
params = {
"Width": ["8"],
"InitValue": [
"0",
"1",
],
"RegisterResetActive": [
"0",
"1",
],
"NumSyncStages": [
"2",
"3",
],
},
top = "br_cdc_stable_data_autoupdate",
deps = [
":br_cdc_stable_data_autoupdate",
"//gate/rtl:br_gate_mock",
],
)
72 changes: 72 additions & 0 deletions cdc/rtl/br_cdc_stable_data_autoupdate.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: Apache-2.0
//
// Bedrock-RTL Stable Data CDC with Automatic Update
//
// This is a thin wrapper around br_cdc_reg for synchronizing an infrequently
// changing multi-bit value. It is similar to br_cdc_stable_data, but the src_valid
// signal is generated automatically based on whether the src_data signal has been changed.
//

`include "br_asserts_internal.svh"
`include "br_registers.svh"

module br_cdc_stable_data_autoupdate #(
parameter int Width = 1,
parameter logic [Width-1:0] InitValue = '0,
parameter bit RegisterResetActive = 1,
parameter int NumSyncStages = 3
) (
input logic src_clk,
input logic src_rst,
input logic [Width-1:0] src_data,

// ri lint_check_waive ONE_LOCAL_CLOCK
input logic dst_clk,
input logic dst_rst,
output logic dst_updated,
output logic [Width-1:0] dst_data
);
// Integration Checks
// Rely on checks in br_cdc_stable_data submodule

// Implementation
logic src_valid;
logic src_ready;
logic [Width-1:0] src_data_reg;

logic dst_updated_next;
logic [Width-1:0] dst_data_next;

`BR_REGLIX(src_data_reg, src_data, src_valid && src_ready, InitValue, src_clk, src_rst)

// Send into the register if the data has changed but hasn't been
// crossed over yet.
assign src_valid = src_data != src_data_reg;

br_cdc_reg #(
.Width(Width),
.RegisterResetActive(RegisterResetActive),
.NumSyncStages(NumSyncStages),
// Data can change if data changes while register is backpressured
.EnableAssertPushDataStability(0)
) br_cdc_reg_inst (
.push_clk (src_clk), // ri lint_check_waive SAME_CLOCK_NAME
.push_rst (src_rst),
.push_valid(src_valid),
.push_ready(src_ready),
.push_data (src_data),

.pop_clk(dst_clk), // ri lint_check_waive SAME_CLOCK_NAME
.pop_rst(dst_rst),
.pop_ready(1'b1),
.pop_valid(dst_updated_next),
.pop_data(dst_data_next)
);

`BR_REGX(dst_updated, dst_updated_next, dst_clk, dst_rst)
`BR_REGLIX(dst_data, dst_data_next, dst_updated_next, InitValue, dst_clk, dst_rst)

// Implementation checks
// TODO(zhemao): Add some here

endmodule : br_cdc_stable_data_autoupdate
52 changes: 52 additions & 0 deletions cdc/sim/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,55 @@ br_verilog_sim_test_tools_suite(
"//gate/rtl:br_gate_mock",
],
)

verilog_library(
name = "br_cdc_stable_data_autoupdate_tb",
srcs = ["br_cdc_stable_data_autoupdate_tb.sv"],
deps = [
"//cdc/rtl:br_cdc_stable_data_autoupdate",
"//misc/sim:br_test_driver",
],
)

verilog_elab_test(
name = "br_cdc_stable_data_autoupdate_tb_elab_test",
tool = "verific",
top = "br_cdc_stable_data_autoupdate_tb",
deps = [
":br_cdc_stable_data_autoupdate_tb",
"//gate/rtl:br_gate_mock",
],
)

br_verilog_sim_test_tools_suite(
name = "br_cdc_stable_data_autoupdate_sim_test_tools_suite",
params = {
"Width": ["8"],
"InitValue": [
"0",
"1",
],
"RegisterResetActive": [
"0",
"1",
],
"NumSyncStages": [
"2",
"3",
],
"SrcClkPeriodNs": [
"10",
"16",
],
"DstClkPeriodNs": [
"10",
"16",
],
},
tools = ["vcs"],
top = "br_cdc_stable_data_autoupdate_tb",
deps = [
":br_cdc_stable_data_autoupdate_tb",
"//gate/rtl:br_gate_mock",
],
)
79 changes: 79 additions & 0 deletions cdc/sim/br_cdc_stable_data_autoupdate_tb.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: Apache-2.0
//
// Bedrock-RTL Stable Data CDC Unit Test
//

module br_cdc_stable_data_autoupdate_tb;
parameter int Width = 8;
parameter logic [Width-1:0] InitValue = '0;
parameter bit RegisterResetActive = 1;
parameter int NumSyncStages = 3;
parameter int SrcClkPeriodNs = 10;
parameter int DstClkPeriodNs = 10;

logic src_clk;
logic src_rst;
logic [Width-1:0] src_data;
logic dst_clk;
logic dst_rst;
logic dst_updated;
logic [Width-1:0] dst_data;

br_cdc_stable_data_autoupdate #(
.Width(Width),
.InitValue(InitValue),
.RegisterResetActive(RegisterResetActive),
.NumSyncStages(NumSyncStages)
) dut (
.src_clk,
.src_rst,
.src_data,
.dst_clk,
.dst_rst,
.dst_updated,
.dst_data
);

br_test_driver #(
.ResetCycles(14)
) td (
.clk(src_clk),
.rst(src_rst)
);

initial dst_clk = 1'b0;
always #(DstClkPeriodNs / 2) dst_clk = ~dst_clk;

initial begin
dst_rst = 1'b1;
src_data = InitValue;

td.reset_dut();

@(negedge dst_clk);
dst_rst = 1'b0;

@(posedge dst_clk);
td.check_integer(dst_data, InitValue, "dst_data initial value mismatch");

for (int i = 5; i < 15; i++) begin
// Send the update
@(negedge src_clk);
src_data = i;

// Wait until we see the update on the destination side
@(posedge dst_clk);
while (!dst_updated) @(posedge dst_clk);
td.check_integer(dst_data, i, "dst_data value mismatch");
// The data should remain stable after update
@(posedge dst_clk);
td.check_integer(dst_data, i, "dst_data value not stable");

// Need to wait some cycles for the source side to be ready again
td.wait_cycles(10);
end

td.finish();
end

endmodule
Loading