I am trying to create a register file in Verilog. To do this, I am instantiating multiple instances of a register module I designed in a generate statement. Each module uses a different input and output signal, so I declared an array of buses and indexed them with the genvar in the loop. When trying to synthesize the module, I receive an error informing me of untrimmed latches.
I am using Xilinx ISE
This is the module code:
module RegisterFile(
input [3:0] RsAddr,
input [2:0] RsShortAddr,
input [3:0] RtAddr,
input [3:0] RdAddr,
input [2:0] RdShortAddr,
input [15:0] WriteAddr,
input [15:0] WriteData,
input WriteEnable,
input Reset,
input Clock,
output reg [15:0] Rs,
output reg [15:0] RsShort,
output reg [15:0] Rt,
output reg [15:0] Rd,
output reg [15:0] RdShort
);
localparam zero = 16'd0, sp = 16'd1, t0 = 16'd1, t1 = 16'd2, t2 = 16'd3,
ra = 16'd5, s0 = 16'd6, s1 = 16'd7, s2 = 16'd8, rv0 = 16'd9, rv1 = 16'd10,
arg0 = 16'd11, arg1 = 16'd12, at = 16'd13, k0 = 16'd14, k1 = 16'd15;
reg [15:0] RegInputMatrix [15:0];
wire [15:0] RegOutputMatrix [15:0];
generate
genvar i;
for (i = 0; i < 15; i = i + 1) begin : RegisterMatrix
Register all_Register-5 5(
.DIN(RegInputMatrix[i]),
.WR_EN(WriteEnable & ~Reset),
.Reset(Reset),
.CLK(Clock),
.DOUT(RegOutputMatrix[i])
);
end
endgenerate
// Write to a register
always @(*) begin
if (Reset)
RegInputMatrix[WriteAddr] <= 16'b0;
else
RegInputMatrix[WriteAddr] <= WriteData;
end
// Decode output logic
always @(posedge Clock or posedge Reset) begin
if (Reset) begin
Rs <= 0;
RsShort <= 0;
Rt <= 0;
Rd <= 0;
RdShort <= 0;
end
else begin
Rs <= RegOutputMatrix[RsAddr];
RsShort <= RegOutputMatrix[RsShortAddr];
Rt <= RegOutputMatrix[RtAddr];
Rd <= RegOutputMatrix[RdAddr];
RdShort <= RegOutputMatrix[RdShortAddr];
end
end
endmodule
I get the following warnings
WARNING:Xst:647 - Input <WriteAddr<15:4>> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:Xst:653 - Signal <RegOutputMatrix<15>> is used but never assigned. This sourceless signal will be automatically connected to value 0000000000000000.
WARNING:Xst:646 - Signal <RegInputMatrix<15>> is assigned but never used. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_0>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_1>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_2>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_3>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_4>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_5>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_6>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_7>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_8>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_9>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_10>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_11>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_12>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_13>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegInputMatrix_14>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
As mentioned above, I believe the Register module is working, but I can provide the hardware description for it if necessary.
2 Answers 2
Your "Write to a register" is not using a clock:
// Write to a register
always @(*) begin
if (Reset)
RegInputMatrix[WriteAddr] <= 16'b0;
else
RegInputMatrix[WriteAddr] <= WriteData;
end
Thus it becomes a latch.
Also that code look suspicious in the reset section. On a reset you only want to clear the register with WriteAddr?
-
\$\begingroup\$ That section is intentionally unclocked. The input matrix is the input line to the register; if I clocked input into the matrix, it would take two clock cycles to write to a register. \$\endgroup\$Nicklas Carpenter– Nicklas Carpenter2019年11月06日 23:52:57 +00:00Commented Nov 6, 2019 at 23:52
Thank you, everyone, for your input. I was able to get the Register File working. The problem ended up being what was described in the first comment on my post (EugeneSh). I was initializing an array of 16 16-bit buses, but only using one at any given time. I only initialized one of the given buses, so the values of the other buses were undefined. Since Verilog needs each bus to have a definite value, it latched each of the signals, so that each signal would hold its previous value if it was not defined.
My solution to the problem involved nixing the input matrix and using a common input line for each register (16 16-bit buses seemed excessive anyway). Instead, I added an enable line ORed with WriteEnable. This new line is only 16 bits and obtains its value from WriteAddr run through a decoder. The write value is brought to the write input of each register, but each register is only written if WriteEnable is high and the register's corresponding enable bit is high. I testing writing to each register with the WriteEnable bit high and low. It worked as expected. I have included the rewritten module below.
module RegisterFile(
input [3:0] RsAddr,
input [2:0] RsShortAddr,
input [3:0] RtAddr,
input [3:0] RdAddr,
input [2:0] RdShortAddr,
input [3:0] WriteAddr,
input [15:0] WriteData,
input WriteEnable,
input Reset,
input Clock,
output reg [15:0] Rs,
output reg [15:0] RsShort,
output reg [15:0] Rt,
output reg [15:0] Rd,
output reg [15:0] RdShort
);
localparam zero = 16'd0, sp = 16'd1, t0 = 16'd1, t1 = 16'd2, t2 = 16'd3,
ra = 16'd5, s0 = 16'd6, s1 = 16'd7, s2 = 16'd8, rv0 = 16'd9, rv1 = 16'd10,
arg0 = 16'd11, arg1 = 16'd12, at = 16'd13, k0 = 16'd14, k1 = 16'd15;
wire [15:0] EnableLine;
wire [15:0] OutputMatrix [15:0];
// Register Write Address Decoder
Decoder Addresser (
.In(WriteAddr),
.Reset(Reset),
.Out(EnableLine)
);
assign OutputMatrix[0] = 0;
generate
genvar i;
for (i = 1; i < 16; i = i + 1) begin : RegisterMatrix
Register all_Register(
.DIN(WriteData),
.WR_EN(~Reset & WriteEnable & EnableLine[i]),
.Reset(Reset),
.CLK(Clock),
.DOUT(OutputMatrix[i])
);
end
endgenerate
// Decode output logic
always @(posedge Clock or posedge Reset) begin
if (Reset) begin
Rs <= 0;
RsShort <= 0;
Rt <= 0;
Rd <= 0;
RdShort <= 0;
end
else begin
Rs <= OutputMatrix[RsAddr];
RsShort <= OutputMatrix[RsShortAddr];
Rt <= OutputMatrix[RtAddr];
Rd <= OutputMatrix[RdAddr];
RdShort <= OutputMatrix[RdShortAddr];
end
end
endmodule
```
RegInputMatrix
in youralways
statement, so it needs latches to keep the previous values. \$\endgroup\$