Iverilog help combinational shift multiplier - verilog

My code compiles but does not dump any dat file for gtkwave. I'm trying to implement a combination shift multiplier object. I don't think my tester is correct.
module combinational_mult(product,multiplier,multiplicand);
input [31:0] multiplier;
input[63:0] multiplicand;
output reg [63:0] product;
reg c;
reg [31:0] m;
integer i;
always #( multiplier or multiplicand )
begin
//initialize
product[63:32] = 16'b0000_0000_0000_0000;
product[32:16] = multiplier;
m = multiplicand;
c = 1'b0;
//add,shift algorithm for unsigned multiplication.
//following the notes.
for(i=0; i<32; i=i+1)
begin
if(product[0]) {c,product[63:32]} = product[63:32] + m ;
product[63:0] = {c,product[63:1]};
c = 0;
end
end
endmodule
module tester(output reg [31:0] multiplier, output reg [63:0] multiplicand, output reg [63:0] product, output reg c, output reg i);
initial begin
i = 0;
$dumpfile("USAMv1.dat");
$dumpvars;
#10 multiplier = 16'b1101_1001_1101_1001;
multiplicand = 16'b0110_1010_1101_1000;
#50 $finish;
end
endmodule
module testbench;
wire[31:0] multiplier;
wire[63:0] multiplicand;
wire[63:0] product;
wire c, i;
tester sim( multiplier, multiplicand, product, c, i);
combinational_mult dut ( product, multiplier, multiplicand);
endmodule

I have created a version on EDA Playground which removes the tester and just runs a test program in the testbench.
I have renamed the dump.dat to dump.vcd to work with EDA Playground. which should launch the wave form window when run.
No real changes to the code other than moving test program to the testbench, and adding a second data point to the test vectors so they can be observed. otherwise the VCD finishes at the point they change.
module testbench;
reg [31:0] multiplier;
reg [63:0] multiplicand;
initial begin
$dumpfile("dump.vcd");
$dumpvars;
#10ns;
multiplier = 16'b1101_1001_1101_1001;
multiplicand = 16'b0110_1010_1101_1000;
#50ns;
multiplier = 16'b0;
multiplicand = 16'b0;
$finish;
end
combinational_mult dut ( product, multiplier, multiplicand);
endmodule

Related

Unexpected high impedance output

I'm writing an ALU for a processor I'm designing (first RTL project) and I'm getting a high impedance output on ALU_out when I run my testbench, even though the flags do get set and are output correctly.
module alu(
input clk,
input reset,
input [7:0] A, B,
input [3:0] Op_Sel,
output [7:0] ALU_out,
output C, V, N, Z
);
reg [8:0] Result = 0;
reg [8:0] cn_temp = 0;
reg [7:0] v_temp = 0;
reg carry = 0;
reg overflow = 0;
reg negative = 0;
reg zero = 0;
assign ALU_Out = Result[7:0];
assign C = carry;
assign V = overflow;
assign N = negative;
assign Z = zero;
always #*
begin
if (reset)
begin
Result = 0;
cn_temp = 0;
v_temp = 0;
carry = 0;
overflow = 0;
negative = 0;
zero = 0;
end
end
always #(posedge clk)
begin
case(Op_Sel)
4'b0000: // Addition
begin
Result = A + B;
negative = Result[7];
zero = (Result[7:0] == 8'b00000000);
carry = Result[8];
v_temp = A[6:0] + B[6:0];
overflow = v_temp[7] ^ carry;
end
.
.
//The rest of the instructions
.
.
.
endcase
end
endmodule
//My testbench
module alu_testbench();
reg clk;
reg reset;
reg [7:0] A;
reg [7:0] B;
reg [3:0] Op_Sel;
wire [7:0] ALU_out;
wire C, V, N, Z;
always begin
#1
clk = ~clk;
end
initial begin
clk = 0;
reset = 0;
#1
reset = 1;
#1
reset = 0;
end
initial begin
#10
A=2;
B=3;
Op_Sel = 4'b0000;
#10
A=1;
end
alu alu (
.clk(clk),
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
endmodule
I believe I connected up the module to the testbench (through a wire), so why am I getting high impedance on ALU_out?
This was a tricky typo. You mistakenly used an upper-case "O" in the ALU_Out signal name. Since Verilog is case-sensitive, this is a different signal from ALU_out. It is not mandatory to declare all signals in Verilog. However, you can use the following compiler directive in your code to help catch this type of common problem:
`default_nettype none
Your simulator should generate an error.
To fix it, change:
assign ALU_Out = Result[7:0];
to:
assign ALU_out = Result[7:0];
My simulators also generated a warning message because you didn't drive the reset input of alu. Here is the fix:
alu alu (
.clk(clk),
.reset(reset), /// <------ add this
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));

Why is logic right shift behaving like arithmetic right shift in this code?

I'm building a floating point adder module and part of it requires 2's complementing and shifting value. The main module code is
module backup (x, y, z, clk);
input [7:0] x,y;
output reg [7:0] z;
input clk;
integer i;
reg [1:0] a;
reg unsigned [7:0] temp;
reg unsigned [8:0] temp2;
always # (posedge clk) begin
a = 2'b00;
temp = 8'b00111100;
temp = ((~temp)+1) >> 2;
$display("temp = %b", temp);
end
endmodule
module backup_tb();
reg [7:0] x,y;
wire [7:0] z;
reg clk;
backup m1 (.x(x),.y(y),.z(z),.clk(clk));
always #10 clk = ~clk;
initial begin
clk = 0;
#50
$finish;
end
endmodule
The output for this code is temp = 11110001 while intended output is temp = 00110001. Please explain what am I missing here, or how can I fix it?
The problem is not with the shift right; it's with the expression ((~temp)+1). You are adding an 8-bit operand to a 32-bit operand, and operands get extended before performing any operations. Numeric literals are implicitly 32-bits. So the bitwise ~ operation inverts 32'b00000000_00000000_00000000_00111100 and then shifts it right. To fix it, yo can write:
temp = ((~temp)+1'b1) >> 2;

Arithmetic right shift not working in Verilog HDL

I am building a shift-unit that is capable of arithmetic and logical right shift, and logical left shift depending on the control signals given to it. However, the arithmetic right shift operator output generates output similar to that logical right shift operator, i.e. sign extension does not occur.
Main code
`timescale 1ns / 1ps
module shift_unit(
input [15:0] a,
input [3:0] b,
input clk,
input isLSL,
input isLSR,
input isASR,
output reg [15:0] result
);
wire [15:0] LSL_result, LSR_result, ASR_result;
LSL lsl(a, b, clk, isLSL, LSL_result);
LSR lsr(a, b, clk, isLSR, LSR_result);
ASR asr(a, b, clk, isASR, ASR_result);
always#(posedge clk) begin
case({isLSL, isLSR, isASR})
3'b001: result <= ASR_result;
3'b010: result <= LSR_result;
3'b100: result <= LSL_result;
endcase
end
endmodule
LSL code:
`timescale 1ns / 1ps
module LSL(
input [15:0] a,
input [3:0] b,
input clk,
input isLSL,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isLSL) result = a << b;
end
assign out = result;
endmodule
LSR code:
`timescale 1ns / 1ps
module LSR(
input [15:0] a,
input [3:0] b,
input clk,
input isLSR,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isLSR) result = a >> b;
end
assign out = result;
endmodule
ASR code:
`timescale 1ns / 1ps
module ASR(
input [15:0] a,
input [3:0] b,
input clk,
input isASR,
output [15:0] out
);
reg [15:0] result;
always#(posedge clk) begin
if(isASR) result = a >>> b;
end
assign out = result;
endmodule
And finally, the testbench:
`timescale 1ns / 1ps
module shift_unit_test;
reg [15:0] a;
reg [3:0] b;
reg clk;
reg isLSL;
reg isLSR;
reg isASR;
wire [15:0] result;
shift_unit uut (
.a(a),
.b(b),
.clk(clk),
.isLSL(isLSL),
.isLSR(isLSR),
.isASR(isASR),
.result(result)
);
always #5 clk = ~clk;
initial begin
clk = 1'b0;
a = 16'b1100101011001010;
b = 4;
{isLSL, isLSR, isASR} = 3'b100; #100;
{isLSL, isLSR, isASR} = 3'b010; #100;
{isLSL, isLSR, isASR} = 3'b001; #100;
end
endmodule
The above code has been modelled using Xilinx ISE 14.7.
Any help would be greatly appreciated.
You need to be working with signed signals to get sign extension.
module ASR(
input wire signed [15:0] a,
input [3:0] b,
input clk,
input isASR,
output reg signed [15:0] out
);
always#(posedge clk) begin
if(isASR) out = a >>> b;
end
endmodule

Red outputs lines - Verilog simulation

I try to simulate in Modelsim my code on Verilog. When I'm simulating it, it shows me X(red) outputs lines. This is my code and testbench:
module alu64bit (
input wire [63:0] a, // Input bit a
input wire [63:0] b, // Input bit b
input wire cin, // Carry in
input wire [1:0] op, // Operation
output wire [63:0] s, // Output S
output wire cout // Carry out
);
wire [63:0] cin_out;
assign cout = cin_out[63];
assign cin = cin_out[0];
genvar i;
generate
for(i=0; i <= 63; i = i + 1) begin
alu1bit alu (.s(s[i]),.cout(cin_out[i+1]),.a(a[i]),.b(b[i]),.cin(cin_out[i]),.op(op));
end
endgenerate
// End of your code
endmodule
TB:
module alu64bit_test;
reg [63:0] a;
reg [63:0] b;
reg [1:0] op;
reg cin;
wire [63:0] s;
wire cout;
alu64bit uut (
.a(a),
.b(b),
.cin(cin),
.op(op),
.s(s),
.cout(cout)
);
initial begin
a = 64'hffffffffffffffff;
b = 64'h0000000000000000;
cin = 0;
op[1] = 1;
op[0] = 0;
#100;
end
endmodule
enter image description here
Can somebody help me with this problem? Thank You!

I understand the fundamentals of verilog, but test bench just won't make sense

Half Adder:
`timescale = 1ns/100ps //timescale ratio //actual HDL
module half_add(a,b,sum, carry);
input a,b;
output sum, carry;
wire sum, carry;
and(sum,a,b);
xor(carry,a,b);
endmodule
Test bench:
module half_addTB;
reg a,b;
wire carry, sum;
//instantiation
half_add half_add1(
.a(a),.b(b),.carry(carry),.sum(sum));
//port assignments with 10ns delays
initial begin
#10 a = 0; b= 0;
#10 b = 1;
#10 a = 1;
#10 b = 0;
end
endmodule
Code compiles fine...but when I try to simulate it, all my values are in a z state....I don't understand why..
You cannot drive inputs to the module from within the module.
Just instantiate your "half_add" module in another module/program (e.g. "half_add_tb") which doesn't have any inputs. then add two local regs "a" and "b", and drive those from an initial block like the one you wrote - but in the "half_add_tb" module instead.
Then just wire up the inputs "a" and "b" of the "half_add" instance to the local "a" and "b" regs.
You need to instantiate your design in a testharness then drive the inputs.
//Half Adder
module half_add(a, b, sum, carry);
input a,b;
output sum, carry;
wire sum, carry; //Outputs are wires by default this is not required
and(sum, a, b);
xor(carry,a, b);
endmodule
module testharness();
//create test signals
reg a; //1 bit reg (regs driven from always and initial blocks)
reg b;
wire sum; // 1 bit wires for outputs to drive
wire carry;
//instantiate DUT (Device under test)
half_add half_add_1(
.a ( a ),
.b ( b ),
.sum ( sum ),
.carry ( carry)
);
//begin testbench
initial begin
#100 $finish;
end
initial begin
#10 a = 0; b= 0;
#10 b = 1;
#10 a = 1;
#10 b = 0;
end
endmodule
NB: if your simulator supports verilog-2001 your port lists can be easier to read and more compact:
//Half Adder
module half_add(
input a,
input b,
output wire sum,
output wire carry
//for regs :
// output reg [WIDTH-1:0] out_reg
//multi-bit wires :
// output [WIDTH-1:0] out_wire
);
and(sum, a, b);
xor(carry,a, b);
endmodule

Resources