Re-declaration of triplicated signals
Summary
When triplicating a block which taps the A/B/C branches of the signals, tmrg ends up defining the signal multiple times
Describe your setup
fastrich
TMRG Version
REPRODUCED_134
Steps to reproduce
module buffer ( input I, input Z);
// tmrg do_not_touch
endmodule
module clock_manager#(parameter int TOA_FINE_BITS=8 )(
input wire clock_i,
input wire enable_i,
input wire [1:0] cfg_ser_sel_i,
input wire [1:0] cfg_bero_sel_i,
output logic clock_40_o,
output logic clock_40_notmr_o,
output logic clock_feedback_o,
output logic [TOA_FINE_BITS-1:0] fine_o,
output logic clock_ser_o,
output logic clock_ser_notmr_o,
output logic tick_ser_o,
output logic clock_bero_o,
output logic clock_bero_notmr_o,
output logic tick_bero_o,
output logic clock_tfc_o
);
// tmrg default triplicate
// tmrg do_not_triplicate fine_o
// tmrg do_not_triplicate clock_40_notmr_o
// tmrg do_not_triplicate clock_ser_notmr_o
// tmrg do_not_triplicate clock_bero_notmr_o
// Divide by 32, no reset
logic [4:0] divider_counts;
wire [4:0] divider_countsVoted = divider_counts; // verilog_lint: waive signal-name-style
logic [4:0] divider_next_counts;
`ifdef SIM
initial #1 divider_counts = $urandom_range(0, 31);
`endif
always @(posedge clock_i) begin
divider_counts <= divider_next_counts;
end
assign divider_next_counts = divider_countsVoted - enable_i;
/*
* Resample generated clocks with 1.28GHz clock
*/
logic clock_40_d_dont_touch;
logic clock_80_d_dont_touch;
logic clock_160_d_dont_touch;
logic clock_320_d_dont_touch;
logic clock_640_d_dont_touch;
always @(posedge clock_i) begin
clock_40_d_dont_touch <= divider_countsVoted[4];
clock_80_d_dont_touch <= divider_countsVoted[3];
clock_160_d_dont_touch <= divider_countsVoted[2];
clock_320_d_dont_touch <= divider_countsVoted[1];
clock_640_d_dont_touch <= divider_countsVoted[0];
end
// Extracting the nontriplicated versions of the clocks
// TMRG will remove the following lines
wire clock_640_d_dont_touchA = clock_640_d_dont_touch; // verilog_lint: waive signal-name-style
wire clock_320_d_dont_touchA = clock_320_d_dont_touch; // verilog_lint: waive signal-name-style
wire clock_160_d_dont_touchA = clock_160_d_dont_touch; // verilog_lint: waive signal-name-style
wire clock_40_d_dont_touchA = clock_40_d_dont_touch; // verilog_lint: waive signal-name-style
buffer clk_fb_buf_dont_touch (
.I(clock_40_d_dont_touch),
.Z(clock_feedback_o)
);
buffer clk_40_buf_dont_touch (
.I(clock_40_d_dont_touch),
.Z(clock_40_o)
);
// tmrg do_not_triplicate clk_40_notmr_buf_dont_touch
buffer clk_40_notmr_buf_dont_touch (
.I(clock_40_d_dont_touchA),
.Z(clock_40_notmr_o)
);
buffer clk_fb_tfc_buf_dont_touch (
.I(clock_320_d_dont_touch),
.Z(clock_tfc_o)
);
// assign clock_feedback_o = clock_40_d_dont_touch;
// assign clock_40_o = clock_40_d_dont_touch;
// assign clock_40_notmr_o = clock_40_d_dont_touchA;
// assign clock_tfc_o = clock_320_d_dont_touch;
endmodule
What is the current bug behavior?
The elaboration fails due to the following signals being declared multiple times
module buffer (
input I,
input Z
);
endmodule
module clock_managerTMR #(
parameter int TOA_FINE_BITS = 8) (
input wire clock_iA,
input wire clock_iB,
input wire clock_iC,
input wire enable_iA,
input wire enable_iB,
input wire enable_iC,
input wire [1:0] cfg_ser_sel_iA,
input wire [1:0] cfg_ser_sel_iB,
input wire [1:0] cfg_ser_sel_iC,
input wire [1:0] cfg_bero_sel_iA,
input wire [1:0] cfg_bero_sel_iB,
input wire [1:0] cfg_bero_sel_iC,
output logic clock_40_oA,
output logic clock_40_oB,
output logic clock_40_oC,
output logic clock_40_notmr_o,
output logic clock_feedback_oA,
output logic clock_feedback_oB,
output logic clock_feedback_oC,
output logic [TOA_FINE_BITS - 1:0] fine_o,
output logic clock_ser_oA,
output logic clock_ser_oB,
output logic clock_ser_oC,
output logic clock_ser_notmr_o,
output logic tick_ser_oA,
output logic tick_ser_oB,
output logic tick_ser_oC,
output logic clock_bero_oA,
output logic clock_bero_oB,
output logic clock_bero_oC,
output logic clock_bero_notmr_o,
output logic tick_bero_oA,
output logic tick_bero_oB,
output logic tick_bero_oC,
output logic clock_tfc_oA,
output logic clock_tfc_oB,
output logic clock_tfc_oC
);
wor divider_countsTmrErrorC;
wire [4:0] divider_countsVotedC;
wor divider_countsTmrErrorB;
wire [4:0] divider_countsVotedB;
wor divider_countsTmrErrorA;
wire [4:0] divider_countsVotedA;
wor clock_40_d_dont_touchATmrError;
wire clock_40_d_dont_touchA;
logic [4:0] divider_countsA;
logic [4:0] divider_countsB;
logic [4:0] divider_countsC;
logic [4:0] divider_next_countsA;
logic [4:0] divider_next_countsB;
logic [4:0] divider_next_countsC;
`ifdef SIM
initial
#1 divider_countsA = $urandom_range(0, 31);
initial
#1 divider_countsB = $urandom_range(0, 31);
initial
#1 divider_countsC = $urandom_range(0, 31);
`endif
always @( posedge clock_iA )
begin
divider_countsA <= divider_next_countsA;
end
always @( posedge clock_iB )
begin
divider_countsB <= divider_next_countsB;
end
always @( posedge clock_iC )
begin
divider_countsC <= divider_next_countsC;
end
assign divider_next_countsA = divider_countsVotedA - enable_iA;
assign divider_next_countsB = divider_countsVotedB - enable_iB;
assign divider_next_countsC = divider_countsVotedC - enable_iC;
logic clock_40_d_dont_touchA; # <---------------REDECLARATION
logic clock_40_d_dont_touchB;
logic clock_40_d_dont_touchC;
logic clock_80_d_dont_touchA;
logic clock_80_d_dont_touchB;
logic clock_80_d_dont_touchC;
logic clock_160_d_dont_touchA;
logic clock_160_d_dont_touchB;
logic clock_160_d_dont_touchC;
logic clock_320_d_dont_touchA;
logic clock_320_d_dont_touchB;
logic clock_320_d_dont_touchC;
logic clock_640_d_dont_touchA;
logic clock_640_d_dont_touchB;
logic clock_640_d_dont_touchC;
always @( posedge clock_iA )
begin
clock_40_d_dont_touchA <= divider_countsVotedA[4];
clock_80_d_dont_touchA <= divider_countsVotedA[3];
clock_160_d_dont_touchA <= divider_countsVotedA[2];
clock_320_d_dont_touchA <= divider_countsVotedA[1];
clock_640_d_dont_touchA <= divider_countsVotedA[0];
end
always @( posedge clock_iB )
begin
clock_40_d_dont_touchB <= divider_countsVotedB[4];
clock_80_d_dont_touchB <= divider_countsVotedB[3];
clock_160_d_dont_touchB <= divider_countsVotedB[2];
clock_320_d_dont_touchB <= divider_countsVotedB[1];
clock_640_d_dont_touchB <= divider_countsVotedB[0];
end
always @( posedge clock_iC )
begin
clock_40_d_dont_touchC <= divider_countsVotedC[4];
clock_80_d_dont_touchC <= divider_countsVotedC[3];
clock_160_d_dont_touchC <= divider_countsVotedC[2];
clock_320_d_dont_touchC <= divider_countsVotedC[1];
clock_640_d_dont_touchC <= divider_countsVotedC[0];
end
buffer clk_fb_buf_dont_touchA (
.I(clock_40_d_dont_touchA),
.Z(clock_feedback_oA)
);
buffer clk_fb_buf_dont_touchB (
.I(clock_40_d_dont_touchB),
.Z(clock_feedback_oB)
);
buffer clk_fb_buf_dont_touchC (
.I(clock_40_d_dont_touchC),
.Z(clock_feedback_oC)
);
buffer clk_40_buf_dont_touchA (
.I(clock_40_d_dont_touchA),
.Z(clock_40_oA)
);
buffer clk_40_buf_dont_touchB (
.I(clock_40_d_dont_touchB),
.Z(clock_40_oB)
);
buffer clk_40_buf_dont_touchC (
.I(clock_40_d_dont_touchC),
.Z(clock_40_oC)
);
buffer clk_40_notmr_buf_dont_touch (
.I(clock_40_d_dont_touchA),
.Z(clock_40_notmr_o)
);
buffer clk_fb_tfc_buf_dont_touchA (
.I(clock_320_d_dont_touchA),
.Z(clock_tfc_oA)
);
buffer clk_fb_tfc_buf_dont_touchB (
.I(clock_320_d_dont_touchB),
.Z(clock_tfc_oB)
);
buffer clk_fb_tfc_buf_dont_touchC (
.I(clock_320_d_dont_touchC),
.Z(clock_tfc_oC)
);
majorityVoter clock_40_d_dont_touchAVoter ( # <---------------DOES NOT LOOK GOOD
.inA(clock_40_d_dont_touchAA),
.inB(clock_40_d_dont_touchAB),
.inC(clock_40_d_dont_touchAC),
.out(clock_40_d_dont_touchA),
.tmrErr(clock_40_d_dont_touchATmrError)
);
majorityVoter #(.WIDTH(5)) divider_countsVoterA (
.inA(divider_countsA),
.inB(divider_countsB),
.inC(divider_countsC),
.out(divider_countsVotedA),
.tmrErr(divider_countsTmrErrorA)
);
majorityVoter #(.WIDTH(5)) divider_countsVoterB (
.inA(divider_countsA),
.inB(divider_countsB),
.inC(divider_countsC),
.out(divider_countsVotedB),
.tmrErr(divider_countsTmrErrorB)
);
majorityVoter #(.WIDTH(5)) divider_countsVoterC (
.inA(divider_countsA),
.inB(divider_countsB),
.inC(divider_countsC),
.out(divider_countsVotedC),
.tmrErr(divider_countsTmrErrorC)
);
endmodule
Possible fixes
- to be investigated.
- blocking https://gitlab.cern.ch/fastrich/design/fastrich_rtl/-/merge_requests/190