Two's complement in verilog - verilog

I've been trying to build a module which returns the two's complement representation of the (3-bit) input (first bit being the sign). I think that the following code is correct conceptually, but I am probably missing something about it's structure: when I try to compile, I get the following errors:
(vlog-2110) Illegal reference to net "f_o".
(vlog-2110) Illegal reference to net "f_o".
(vlog-2110) Illegal reference to net "f_o".
Searching for that error showed it is usually seen when using a variable as input and output at the same time, but that's not my case. Could you point where the error is?
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
always #(a_i[2:0] or f_o[2:0])
begin
if (a_i[2] == 1)
begin
f_o[2] = a_i[2];
f_o[1:0] = (~a_i[1:0] + 'b1);
end
else
begin
f_o = a_i;
end
end
endmodule

In Verilog, undeclared identifiers are considered implicit wire declarations in most circumstances. Since f_o has not been declared the compiler considers it a wire, not a variable. This causes the compiler to complain about all the assignments.
// What was typed
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
// What the compiler implicitly declares
wire [2:0] a_i;
wire [2:0] f_o;
To fix it you can declare the variable or declare both the port and the variable.
module ca2 (a_i,f_o);
input [2:0] a_i;
output [2:0] f_o;
reg [2:0] f_o;
module ca2 (a_i,f_o);
input [2:0] a_i;
output reg [2:0] f_o;

f_o needs to be declared as a reg. output reg [2:0] f_o.
Also I am not sure what you are calculating, that is not a standard twos complement.
module ca2 (
input [2:0] a_i,
output [2:0] twos_comp,
output [2:0] also_twos_comp
);
assign twos_comp = ~a_i + 1'b1;
assign also_twos_comp = -a_i ;
endmodule
You may be dealing with an encoded input, but twos_complement is to negate the number I would expect the sign bit (MSB) to change. Although we refer to it as a sign bit it also contains information about the value and therefore can not just be stripped off and leave the number unchanged.

The first solution -> In sequential circuits, the output must be in the form of a reg.
and Next we need to know that in two's complement we start from bit zero to get to the end so the condition is incorrect.
If the zero bit is one, then the zero bit is unchanged and the rest of the bits change to not.
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
always #(a_i[2:0] or f_o[2:0]) begin
if (a_i[0] == 1'b1) begin
f_o[0] = a_i[0];
f_o[2:1] = (~a_i[2:1]);
end
else
if(a_i[1]==1'b1) begin
f_o[1:0] = a_i[1:0];
f_o[2] = (~a_i[2]);
end
else
if(a_i[2] == 1'b1) begin
f_o = a_i ;
end
end
endmodule
The second solution -> In binary numbers, if we subtract the number from zero, we get two's complement .
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
always #(a_i[2:0] or f_o[2:0]) begin
f_o = 3'b000 - a_i ;
end
endmodule
The third solution -> all bits change to not and Finally, they are added to the number one (3'b000 = 3'b0)
module ca2 (input [2:0] a_i,output reg [2:0] f_o);
reg [2:0] finish ;
always #(a_i[2:0] or f_o[2:0]) begin
finish = (~a_i);
f_o = finish + 3'b001 ;
end
endmodule

Related

Prevent Latch for Register File implementation [duplicate]

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.

ALU in Verilog: "Unable to bind wire/reg/memory"

I am trying to make a simple 32 bit ALU with an overflow flag, and then output the inputs and results of the ALU to the screen, but I encountered some problems with connecting the elements for the test bench. I got this error:
test_32bALU.v:15: error: Wrong number of ports. Expecting 4, got 5.
test_32bALU.v:33: error: Unable to bind wire/reg/memory
test_unit.overflow' inalu_test'
2 error(s) during elaboration.
I am just starting with Verilog and I have a basic idea of the syntax. I know I am not supposed to ask debugging questions, but this is my only hope. My professor or TA wouldn't respond to me requests for help. I would appreciate it if anyone here could help me point out my mistakes.
This is my 32bALU.v file:
module alu(
input signed[31:0] a,b,
input[3:0] opcode;
output signed[31:0] c;
output overflow;
);
reg signed[31:0] result;
assign c = result;
reg tmp;
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
always #(a,b,opcode)
begin
case(opcode)
add:
begin
c = a + b;
end
endcase
end
always #(c)
begin
if (c[32:31] == (2'b11 | 2'b10)) // Overflow
begin
tmp = 1'b1;
assign overflow = tmp;
end
else begin
tmp = 1'b0;
assign overflow = tmp;
end
end
assign result = c[31:0];
endmodule
test_32bALU.v
`timescale 1ns/1ps
module alu_test;
// Inputs
reg[31:0] a,b;
reg[2:0] opcode;
// Outputs
wire[31:0] c;
//wire [1:0] zero;
wire [1:0] overflow;
//wire [1:0] neg;
alu test_unit(
a,b, // Inputs
opcode,
c,
overflow
);
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
initial begin
$display("op: a : b : c : reg_A : reg_B : reg_C");
$monitor(" %h:%h:%h:%h:%h:%h:%h",
opcode, a, b, c, test_unit.a, test_unit.b, test_unit.c);
$monitor("%h", test_unit.overflow);
//// add
#10 a=32'b0000_0000_0000_0000_0000_0000_0000_0001;
#10 b=32'b0000_0000_0000_0000_0000_0000_0000_0001;
opcode= add;//3'b000
#10 $finish;
end
endmodule
I am confused as to why it says "wrong number of ports"? I assume it's the number of parameters in module alu and alu test_unit? They have the same number of parameters (a, b, c, opcode and overflow), so what exactly am I missing? How exactly do I get the value of overflow? It works fine before I added the overflow parameter, so I assume I'm doing it wrong?
For the second error, I read somewhere on here that it might be due to a missing declaration, but I have declared all of them... so I am not sure what's making it wrong.
I am not sure if this is the issue, but your module definition is not correct. It should be as follows:
module alu(
input signed[31:0] a,b,
input[3:0] opcode,
output signed[31:0] c,
output overflow
);
Perhaps this may help with your issue.
Commas separate inputs and outputs in the module declaration.
NEVER rely on the order of arguments to modules and ALWAYS try to use, for a module called A;
module A(output wire c,
input wire a,
input wire b);
...
endmodule // A
use an instance of it using;
A yourAname(.c(Bar),
.a(Foo1),
.b(Foo2));
so that if the definition and order of the I/O of the module changes, this instantiation will track those changes and/or give appropriate errors when simulated/synethesised.
You might find it useful to follow a few simple rules in your source code when naming;
inputs are denoted by i_yourinputname
outputs are denoted by o_youroutputname
inout are denoted by io_yourinputoutputname
wire are denoted by w_yourwirename
reg are denoted by r_yourregname
as this avoid confusion and is a good habit to get into as soon as possible when starting to learn verilog.

Error (10734): Verilog HDL error at SWSelector.v(13): selector is not a constant

Referring to my previous post:
Error (10482): VHDL error: object "select_vector" is used but not declared
I converted my code from VHDL to verilog, but I'm getting this error now:
(Error (10734): Verilog HDL error at SWSelector.v(13): selector is not
a constant),
Any suggestions how do I deal with it? There are 8 possibilities for selector switch which are coming from a decoder. So whenever the value of selector matches 3'b000, I want rq to be assigned to requests. Here is my code:
module SWSelector(
input [7:0] rq,
input [2:0] selector,
output [7:0] request
);
localparam NUM=3'b000;
generate
genvar i;
for(i=0;i<7;i=i+1)
begin: label
if(selector == NUM)
begin
assign request[i] = rq[i];
end
else
begin
assign request[i]=0;
end
end
endgenerate
endmodule
Since your if-statement is in a generate, you're asking the tool to pre-evaluate what selector is set to in order to figure out selecter == NUM evaluates to, but your tool doesn't know because it's a signal, not a parameter.
You want to use the generate to create an always block that you can check the value of selector in, like so:
module SWSelector(
input [7:0] rq,
input [2:0] selector,
output reg [7:0] request
);
localparam NUM=3'b000;
generate
genvar i;
for(i=0;i<7;i=i+1)
begin: label
always #* begin
if(selector == NUM)
request[i] = rq[i];
else
request[i]=0;
end
end
endgenerate
endmodule
Or, as toolic said, you can use a ternary and an assign.
Edit:
Without generate:
module SWSelector(
input [7:0] rq,
input [2:0] selector,
output reg [7:0] request
);
localparam NUM=3'b000;
integer i;
always #* begin
for(i=0;i<7;i=i+1)
if(selector == NUM)
request[i] = rq[i];
else
request[i]=0;
end
endmodule

How to store input into reg from wire in verilog?

I' trying to store value from wire named 'in' into reg 'a'.
But, the problem is value of reg 'a' is showing 'xxxx' in simulator. However, value of wire 'in' is showing correctly.
My target is just to read value from input wire and store it into a register.
module test(
input [3:0] in,
output [3:0] out
);
reg [3:0] a;
initial
begin
a = in;
end
endmodule
The reason why the value of a is 'xxxx' in the simulation is probably that a is set to the value of in only a single time initially, and a may not yet have been set to any specific value at this time in the simulation.
Declaring a reg in Verilog does not necessarily mean that a hardware register is described by the code. That usually involves the use of a clock signal:
module test(
input clk,
input [3:0] in,
output [3:0] out
);
// this describes a register with input "in" and output "a"
reg [3:0] a;
always #(posedge clk) begin
a <= in;
end
// I assume you want "a" to be the output of the module
assign out = a;
endmodule
Here is a counter example where a reg is used to describe something which is not a register, but only a simple wire:
module not_a_register(
input in,
output out
);
reg a;
always #(in) begin
a <= in;
end
assign out = a;
endmodule
Also note that I have used the non-blocking assignment operator <= inside the always block, which is good practice when describing synchronous logic. You can read more about it here.

number of ones in array

I am trying to count the number of ones in a 4-bit binary number in Verilog, but my output is unexpected. I've tried several approaches; this is the one I think should work, but it doesn't.
module ones(one,in);
input [3:0]in;
output [1:0]one;
assign one = 2'b00;
assign one = one+in[3]+in[2]+in[1]+in[0] ;
endmodule
First, you can't assign the variable twice.
Second, your range is off, 2 bits can only go from 0 to 3. You need a 3 bit output to count up to 4.
This is more like what you need:
module ones(
output wire [2:0] one,
input wire [3:0] in
);
assign one = in[3]+in[2]+in[1]+in[0] ;
endmodule
$countones can be used for this purpose (refer to IEEE Std 1800-2012, 20.9 Bit vector system functions):
module tb;
reg [3:0] in;
wire [2:0] one = $countones(in);
initial begin
$monitor("in=%b one=%d", in, one);
#1 in = 4'b0000;
#1 in = 4'b0001;
#1 in = 4'b1101;
end
endmodule
Output:
in=xxxx one=0
in=0000 one=0
in=0001 one=1
in=1101 one=3

Resources