This question already has answers here:
Why is this code getting inferred latches?
(2 answers)
Closed 5 months ago.
I am design a register file module and I am trying to prevent the "inferred latch warning". The module allows for asynchronous reads but synchronous writes. This is what I have designed so far. I generally know what latches are, but can't think of a solution to prevent latches in this case. What would I define as the else statement so that the regfile doesn't create inferred latches?
module register_file (
input wire clk,
input wire rst,
input wire [4:0] raddr_a,
input wire [4:0] raddr_b,
output reg [15:0] rdata_a,
output reg [15:0] rdata_b,
input wire [4:0] waddr,
input wire [15:0] wdata,
input wire we
);
reg [15:0] regfile [0:31];
/// 32 x 16 bit register file
// asynchronous reads
// don't allow read zero register
assign rdata_a = (raddr_a == 5'd0) ? 16'd0 : regfile[raddr_a];
assign rdata_b = (raddr_b == 5'd0) ? 16'd0 : regfile[raddr_b];
integer i;
always #(clk) begin
// reset registers
if (rst) begin
for (i = 0; i < 32; i = i + 1) begin
regfile[i] <= 0;
end
end else begin
// if write enabled, write to register at waddr
if (we == 1'b1) begin
regfile[waddr] <= wdata;
end
end
end
endmodule
Would I set the value to itself? How would I go on preventing an inferring latch? Thanks!
Change always statement from:
always #(clk) begin
to:
always #(posedge clk) begin
I was able to run the posted code on EDA Playground Yosys; it produces latches.
After the change, latches are no longer produced.
I want to use SW[15] to switch between module A_7seg and B_7seg but it does not work. (2 modules work separately)
module mix(input CLOCK,input [15:0]SW,output reg [15:0] led,output [3:0] an,output reg[7:0] seg);
generate
case(SW[15])
1'b0:A_7seg (.CLOCK(CLOCK),.an(an),.seg(seg));
1'b1:B_7seg (.CLOCK(CLOCK),.SW(SW),.led(led),.an(an),.seg(seg));
endcase
endgenerate
endmodule
Since '2 modules work separately', the simple way is to use SW[15] to select between 2 modules' outputs.
module mix(
input CLOCK,
input [15:0] SW,
output reg [15:0] led,
output reg [3:0] an,
output reg [7:0] seg
);
wire [15:0] B_led;
wire [3:0] A_an, B_an;
wire [7:0] A_seg, B_seg;
// if not using 'generate' block, modules are instantiated at
// the top level, not in other 'if'/'case'/... structures.
// and name the 2 instantiations
A_7seg u_A_7seg (.CLOCK(CLOCK), .an(A_an), .seg(A_seg));
B_7seg u_B_7seg (.CLOCK(CLOCK), .SW(SW), .led(B_led), .an(B_an), .seg(B_seg));
// this extra circuit is needed to select between the two
always#(*)begin
if(SW[15])begin
led = B_led;
an = B_an;
seg = B_seg;
end
else begin
led = 16'h0; // <-- I assume the inactive value for 'led' is all-zero
an = A_an;
seg = A_seg;
end
end
endmodule
You may also want to use SW[15] to gate the inputs to the one that is not currently working to reduce power consumption.
You need to figure out the schematic before you understand how to write the code.
I want to make Frequency Divider with Counter and MUX.
I make 3 module for project
// 4-bit Counter
module Counter (input clk, input reset, output reg[3:0] out);
always#(posedge clk or posedge reset)
begin
if(reset)
out = 4'b0000;
else
begin
if(clk)
if(out < 4'b1111)
out = out + 4'b0001;
else
out = 4'b0000;
end
end
endmodule
//module 4by1 Mux
module Mux (input [3:0] muxin , input [1:0] sel, output reg muxout);
function _4by1mux;
input [3:0] muxin;
input [1:0] sel;
case (sel)
2'b00 : _4by1mux = muxin[0];
2'b01 : _4by1mux = muxin[1];
2'b10 : _4by1mux = muxin[2];
2'b11 : _4by1mux = muxin[3];
endcase
endfunction
assign muxout = _4by1mux(muxin, sel);
endmodule
//module freqDivider
module freqDivider(input clk, input reset, input [1:0] sel, output reg muxout);
wire [3:0]counterbus;
Counter ct1 (clk, reset, counterbus);
Mux mux1 (counterbus, sel, muxout);
endmodule
module freqDivider is top, and I call module Counter and Mux
but module Mux has problem with
Error (10219): Verilog HDL Continuous Assignment error at Mux.v(19):
object "muxout" on left-hand side of assignment must have a net type
this error
ps. input sel will be changed by time
The error is a result of the muxout output having type reg instead of type wire. In verilog, lines can have two overarching types, either nets (like wire type) or variables (like reg types). To assign values/logic to net types, you need to use assign statements and not always blocks. To assign values/logic to variable types, you can only use always blocks and not assign statements. So, you can either make your assign in the Mux module an always block or, for an easier solution, don't make the muxout output a reg, just leave out the reg keyword and it will be a wire.
Error is that you have declared mux_out as reg type, instead of wire type. Default type of any port is wire. You are doing continuous assignment on that net through assign keyword. And on reg type nets, assignment can only be done inside procedural block (initial, always).
Change to mux_out from output reg to output only.
I am working on a ripple carry adder using structural verilog, which is supposed to take in two random inputs and calculate accordingly.
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Could someone kindly explain where I'm going wrong? Below is my code:
module full_adder(x,y,z,v,cout);
parameter delay = 1;
input x,y,z; //input a, b and c
output v,cout; //sum and carry out
xor #delay x1(w1,x,y);
xor #delay x2(v,w1,z);
and #delay a1(w2,z,y);
and #delay a2(w3,z,x);
and #delay a3(w4,x,y);
or #delay o1(cout, w2,w3,w4);
endmodule
module four_bit_adder(a,b,s,cout,cin);//four_bit_adder
input [15:0] a,b; //input a, b
input cin; //carry in
output [15:0] s; //output s
output cout; //carry out
wire [15:0] c;
full_adder fa1(a[0],b[0],cin,s[0],c0);
full_adder fa2(a[1],b[1],c0,s[1],c1);
.
.
.
full_adder fa16(a[15],b[15],c14,s[15],cout);
endmodule
module testAdder(a,b,s,cout,cin);
input [15:0] s;
input cout;
output [15:0] a,b;
output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
initial begin
for(i=0; i<5000; i=i+1) begin
a = $random(seed1);
b = $random(seed2);
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
Here are two lines from the output that I get:
a=38893, b=58591, cin=x, s= z, cout=z
a=55136, b=58098, cin=x, s= z, cout=z
This is a combinational circuit, so the output changes instantaneously as the input changes. But, here you are apply all the inputs at same timestamp which should not be done since the full_adder module provides 1-timestamp delay. This may not cause problems in this module, but may cause issues while modelling sequential logic. Add a minimum of #10 delay between inputs.
Also, $monitor executes on each change in the signal list, so no need to use it in for loop. Just initialize $monitor in initial condition.
cin is also not driven from the testbench. Default value of reg is 'x and that of wire is 'z. Here, cin is reg, so the default value is displayed, that is 'x
One more thing, you must instantiate the design in your testbench. And connect respective ports. The outputs from testbench act as inputs to your design and vice-versa. This is just like you instantiate full_adder module in four_bit_adder module in design.
Consider testadder as top level module and instantiate design in it. No need of declaring ports as input and output in this module. Declare the design input ports as reg or wire(example: reg [15:0] a when a is design input port) and output ports as wire (example: wire [15:0] sum when sum is design input port).
Referring to your question:
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Instead of using $random, use $urandom_range() to generate random numbers in some range. Using SystemVerilog constraints constructs can also help. Refer this link.
Using $urandom_range shall eliminate use of seed1 and seed2, it shall generate random values with some random machine seed.
Following is the module testadder with some of the changes required:
module testAdder();
wire [15:0] s;
wire cout;
// output [15:0] a,b;
// output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
// Instantiate design here
four_bit_adder fa(a,b,s,cout,cin);
initial begin
// Monitor here, only single time
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
for(i=0; i<5000; i=i+1) begin
// Drive inputs with some delays.
#10;
// URANDOM_RANGE for input generation in a range
a = $urandom_range(0,15);
b = $urandom_range(0,15);
// a = $random(seed1);
// b = $random(seed2);
// Drive cin randomly.
cin = $random;
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
For more information, have a look at sample testbench at this link.
Can I use a wire inside an always block?
Like for example:
wire [3:0]a;
assign a=3;
always #(c)
begin
d=a+c;
end
It got compiled without throwing any error. Why?
Yes, you can use a wire's value inside an always block, you just can not assign a value to a wire in always or initial block.
The only real difference between a wire and reg is the syntax for assigning values.
In the above example d could also have been created as a wire, these are equivalent:
reg [3:0] answer_reg;
always #* begin
answer_reg = a + c;
end
wire [3:0] answer_wire;
assign answer_wire = a + c;