Arithmetic right shift not working in Verilog HDL - verilog

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

Related

How to get more info in testbench results?

I realize that this may be very easy to fix but I can't find a way to make it work.
My question is how can I get visual signals of CE2 and CEO in this case? I know by looking on RTL Scheme CE2 and CEO isn't connected to pins. And I just can't connect them.
CE2 should be ON when first counter reach 9 but on waveform its always as X. And CEO should be ON when Q is 9 but on waveform its always Z.
This circuit is just for self learning.
Testbench
Circuit Scheme
TOP MODULE:
`timescale 1ns / 1ps
module top(
input CLK,
input CLR,
input CE,
input CE2,
output reg [3:0] Q,
output reg [3:0] Q2,
output wire CEO,
output CEO2
);
wire CLK;
wire CLR;
wire CENABLE;
wire CE2;
wire Q;
wire Q2;
wire CEO;
wire CEO2;
licznik licznik(.CLK(CLK),.CLR(CLR),.CE(CE),.CEO(CENABLE),.Q(Q));
licznik2 licznik2(.CLK(CLK),.CLR(CLR),.CE2(CENABLE),.Q2(Q2),.CEO2(CEO2));
endmodule
TESTBENCH:
`timescale 1ns / 1ps
module testbench;
reg CLK;
reg CLR;
reg CE;
reg CE2;
wire [3:0] Q;
wire [3:0] Q2;
wire CEO;
wire CEO2;
top UUT (
.CLK(CLK),
.CLR(CLR),
.CE(CE),
.CE2(CE2),
.Q(Q),
.Q2(Q2),
.CEO(CEO),
.CEO2(CEO2)
);
initial CLK=1'b0;
always #5 CLK=~CLK;
initial
begin
CLR = 1'b1;
CE= 1'b1;
#18 CLR = 1'b0;
end
endmodule
FIRST MODULE:
`timescale 1ns / 1ps
module licznik(
input CLK,
input CLR,
input CE,
output reg [3:0] Q,
output CEO
);
always #(posedge CLK or posedge CLR)
if(CLR)
Q <= 4'd0;
else begin
if(CE) begin
if(Q != 4'd9)
Q <= Q + 1;
else
Q <= 4'd0;
end
end
assign CEO = CE & (Q == 4'd9);
endmodule
SECOND MODULE:
`timescale 1ns / 1ps
module licznik2(
input CLK,
input CLR,
input CE2,
output reg [3:0] Q2,
output CEO2
);
always #(posedge CLK or posedge CLR)
if(CLR)
Q2 <= 4'd0;
else begin
if(CE2) begin
if(Q2 != 4'd9)
Q2 <= Q2 + 1;
else
Q2 <= 4'd0;
end
end
assign CEO2 = CE2 & (Q2 == 4'd9);
endmodule
I ran your code on 2 simulators, and I got compile errors on both. Try your code on EDAPlayground.
To fix the compile errors, I removed the wire declarations in module top. To fix the problem with Z on CEO, I replaced CENABLE with CEO. Here is the new top module:
module top(
input CLK,
input CLR,
input CE,
input CE2,
output reg [3:0] Q,
output reg [3:0] Q2,
output wire CEO,
output CEO2
);
licznik licznik(.CLK(CLK),.CLR(CLR),.CE(CE),.CEO(CEO),.Q(Q));
licznik2 licznik2(.CLK(CLK),.CLR(CLR),.CE2(CEO),.Q2(Q2),.CEO2(CEO2));
endmodule
CE2 is X because it is an undriven input. I think you can just delete it.

verilog AND gate when 32 not working correctly

The AND gate
module andgate
#(parameter Port_Num = 2,
parameter WIDTH=8)
(
input [(WIDTH-1):0] a,
input [(WIDTH-1):0] b,
input [(WIDTH-1):0] c,
input [(WIDTH-1):0] d,
input [(WIDTH-1):0] e,
input [(WIDTH-1):0] f,
input [(WIDTH-1):0] g,
input [(WIDTH-1):0] h,
output [(WIDTH-1):0] q
);
assign q = (a & b & c & d & e & f & g & h);
endmodule
The angate_sim
`timescale 1ns / 1ps
module andgate_sim();
// input
reg a=0;
reg b=0;
reg c=1;
reg d=1;
reg e=1;
reg f=1;
reg g=1;
reg h=1;
//outbut
wire q;
andgate #(8,1) u(.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.h(h),.q(q));
always #100 a=~a;
initial begin
#100 a=1;
#100 begin a=0;b=1;end
#100 a=1;
#60000000 $finish;
end
initial
begin
$dumpfile("wave2.vcd");
$dumpvars(0, andgate_sim);
end
endmodule
When I test the testbench, it worked correctly like this
iverilog -o Ex2 andgate.v andgate_sim.v
vvp -n Ex2 -lxt2
gtkwave wave2.vcd
The successful wave in wave2.vcd
Then I tried to make a AND gate*32 just like this
`timescale 1ns / 1ps
module andgate32_sim( );
// input
reg [31:0] a=32'h00000000;
reg [31:0] b=32'h00000000;
reg [31:0] c=32'hffffffff;
reg [31:0] d=32'hffffffff;
reg [31:0] e=32'hffffffff;
reg [31:0] f=32'hffffffff;
reg [31:0] g=32'hffffffff;
reg [31:0] h=32'hffffffff;
//outbut
wire [31:0] q;
andgate #(8,32) u(.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.h(h),.q(q));
always #100
begin
a <= 32'hffffffff;
end
always #200
begin
a <= 32'h00000000;
b <= 32'hffffffff;
end
always #300
begin
a <= 32'h007fa509;
end
always #400
begin
a <= 32'hffffffff;
end
initial begin
#100 a <= 32'hffffffff;
#100 begin a <= 32'h00000000;b <= 32'hffffffff;end
#100 a <= 32'h007fa509;
#100 a <= 32'hffffffff;
#60000000 $finish;
end
initial
begin
$dumpfile("wave2-2.vcd");
$dumpvars(0, andgate32_sim);
end
endmodule
But when I did the steps like before
iverilog -o Ex2 andgate.v andgate32_sim.v
vvp -n Ex22 -lxt2
gtkwave wave2-2.vcd
There was nothing in the wave like this
No waves in the wave2-2.vcd
Actaully, it should be something in the wave2-2.vcd.
Could you please help me ?
You are trying to run another compiled testbench "Ex22" instead of "Ex2".
Hint: You can use parameters and pass them to the instantiation, as:
localparam WIDTH = 32;
localparam Port_Num = 8;
// input
reg [WIDTH-1:0] a=32'h00000000;
reg [WIDTH-1:0] b=32'h00000000;
reg [WIDTH-1:0] c=32'hffffffff;
reg [WIDTH-1:0] d=32'hffffffff;
reg [WIDTH-1:0] e=32'hffffffff;
reg [WIDTH-1:0] f=32'hffffffff;
reg [WIDTH-1:0] g=32'hffffffff;
reg [WIDTH-1:0] h=32'hffffffff;
//outbut
wire [WIDTH-1:0] q;
andgate #(.Port_Num (Port_Num), .WIDTH (WIDTH)) u(.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.h(h),.q(q));

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!

Always loop Verilog

This my Verilog code to convert the number x into form x=a0*R+a1 ,e.g 51 = 5*10 +1. My code does not work, it cannot enter the always loop.
`timescale 1ns / 1ps
module poly(
input [15:0] r,
input [15:0] x,
output reg[15:0] a1,
output reg [15:0] a0,
output finish,
input clk,
input reset
);
reg [15:0] sum;
assign finish =(sum > x);
always# (posedge clk )
begin
if(reset)
begin
a0 <=0;
sum <=0;
end
else if (!finish)
begin
a0 <=a0+1;
sum <= sum+r;
end
else
a1<=x-sum;
end
initial begin
$monitor ( "a1=%b,a0=%b,finish=%b,reset=%b",a1,a0,finish,reset);
end
endmodule
testbench
`timescale 1ns / 1ps
module tb_p;
reg [15:0] r;
reg [15:0] x;
wire[15:0] a1;
wire [15:0] a0;
wire finish;
reg clk;
reg reset;
initial clk=0;
always #5 clk=!clk;
poly m1(r,x,a1,a0,finish,clk,reset);
initial begin
r<=10;
x <=17;
#1 reset<=1;
#2 reset<=0;
end
endmodule
Since your reset signal is synchronous to the clock, you need to extend it so that it is high for at least one posedge of the clock:
initial begin
r<=10;
x <=17;
#1 reset<=1;
#20 reset<=0;
#500 $finish;
end
Note that I added $finish just so my simulation would end.

Error in testbench as Inout port 'A' of 'DIGITADD' must be a net

module DIGITADD(
input [3:0] A,
input [3:0] B,
input CIN,
output COUT,
output [3:0] SUM
);
reg [4:0] s2;
assign SUM = s2[3:0];
assign COUT = s2[4];
//BCD ADDER PART
always # ( * )
begin
s2 = A + B + CIN;
if (s2 > 9)
begin
s2 = s2 + 6;
end
end
endmodule
TEST BENCH
module DIGITADD_tb(
reg [3:0] A,
reg [3:0] B,
reg CIN,
wire COUT,
wire [3:0] SUM);
DIGITADD uut(
.A(A),
.B(B),
.CIN(CIN),
.COUT(COUT),
.SUM(SUM));
initial begin
$dumpfile("dump.vcd");
$dumpvars(1,DIGITADD_tb);
#10;
#10 A=4'b0000;B=4'b0011;CIN=1'b0;
#10 A=4'b0111;B=4'b1000;CIN=1'b1;
$finish;
end
endmodule
You have added local variables in your testbench in the style of a port list:
module DIGITADD_tb(
reg [3:0] A,
reg [3:0] B,
reg CIN,
wire COUT,
wire [3:0] SUM);
Should be:
module DIGITADD_tb(); //<-- no ports
reg [3:0] A; //<-- semicolon
reg [3:0] B;
reg CIN;
wire COUT;
wire [3:0] SUM;

Resources