How do I add an input called Unsigned / Signed for Verilog comparator testbench code? - verilog

I'm new to coding verilog.
This is code for a 3-bit Comparator. I need help adding a signal called 'US' (unsigned/signed) to my testbench code. When the signal is High(unsigned mode), the Comparator interprets the numbers as Unsigned numbers. When the signal is Low (Signed Mode), the Comparator interprets the numbers as signed numbers.
module comparator(A,B,G,E,L,US);
input [2:0]A;
input [2:0]B;
input US;
output G,E,L;
reg G,E,L;
always#(*)
begin
if(US==0)
begin
L=$signed(A)<$signed(B);
E=$signed(A)==$signed(B);
G=$signed(A)>$signed(B);
end
else
L = A < B;
E = A==B;
G = A > B;
end
endmodule
TEST BENCH CODE:
`timescale 1ns /1ps
module comparator_tb();
reg [2:0]A=3'b000;
reg [2:0]B=3'b000;
reg US;
wire G,E,L;
integer i,j;
comparator uut(A,B,G,E,L,US);
initial begin
for(i=0;i<8;i=i+1)
begin
for(j=0;j<8;j=j+1)
begin
#50
B=B+1;
end
A = A+1;
B=3'b000;
end
#100
$stop;
end
endmodule

i guess you want to toggle US in your test bench. something like the following?
since US is declared as wire (default), you need the assign statement:
integer us_count;
assign US = us_count;
initial begin
for(us_count = 0; us_count < 1; us_count++) begin
for(i=0;i<8;i=i+1)
begin
for(j=0;j<8;j=j+1)
begin
#50
B=B+1;
end
A = A+1;
B=3'b000;
end
end
#100
$stop;
end
if you declare it as reg, you can use it directly in the loop instead of the us_count and do not need the assign
reg US;
initial begin
for (US = 0; US < 1; US++)
...
The rest depends on how you want to test it.

Related

Verilog code 2 errors i can't find: Would be grateful for an extra pair of eyes to spot a mistake i might've overlooked

I'm writing a verilog code where i'm reading two files and saving those numbers into registers. I'm then multiplying them and adding them. Pretty much a Multiplication Accumulator. However i'm having a hard frustrating time with the code that i have. It read the numbers from the files correctly and it multiples but here is the problem? When i first run it using ModelSim, I reset everything so i can clear out the accumulator. I then begin the program, but there is always this huge delay in my "macc_out" and i cannot seem to figure out why. This delay should not be there and instead it should be getting the result out A*B+MAC. Even after the delay, it's not getting the correct output. My second problem is that if i go from reset high, to low (start the program) and then back to reset high ( to reset all my values), they do not reset! This is frustrating since i've been working on this for a week and don't know/can't see a bug. Im asking for an extra set of eyes to see if you can spot my mistake. Attached is my code with the instantiations and also my ModelSim functional Wave Form. Any help is appreciated!
module FSM(clk,start,reset,done,clock_count);
input clk, start, reset;
output reg done;
output reg[10:0] clock_count;
reg [0:0] macc_clear;
reg[5:0] Aread, Bread, Cin;
wire signed [7:0] a, b;
wire signed [18:0] macc_out;
reg [3:0] i,j,m;
reg add;
reg [0:0] go;
reg[17:0] c;
parameter n = 8;
reg[1:0] state;
reg [1:0] S0 = 2'b00;
reg [1:0] S1 = 2'b01;
reg [1:0] S2 = 2'b10;
reg [1:0] S3 = 2'b11;
ram_A Aout(.clk(clk), .addr(Aread), .q(a));
ram_B Bout(.clk(clk), .addr(Bread), .q(b));
mac macout(.clk(clk), .macc_clear(macc_clear), .A(a), .B(b), .macc_out(macc_out), .add(add));
ram_C C_in(.clk(clk), .addr(Cin), .q(c));
always #(posedge clk) begin
if (reset == 1) begin
i <= 0;
add<=0;
j <= 0;
m <= 0;
clock_count <= 0;
go <= 0;
macc_clear<=1;
end
else
state<=S0;
case(state)
S0: begin
// if (reset) begin
// i <= 0;
// add<=0;
// j <= 0;
// m <= 0;
// clock_count <= 0;
// go <= 0;
// macc_clear<=1;
// state <= S0;
// end
macc_clear<=1;
done<=0;
state <= S1;
end
S1: begin
add<=1;
macc_clear<=0;
clock_count<=clock_count+1;
m<=m+1;
Aread <= 8*m + i;
Bread <= 8*j + m;
if (m==7) begin
state <= S2;
macc_clear<=1;
add<=0;
end
else
state <=S1;
end
S2: begin
add<=1;
macc_clear<=0;
m<=0;
i<=i+1;
if (i<7)
state<=S1;
else if (i==8) begin
state<=S3;
add<=0;
end
end
S3: begin
add<=1;
i<=0;
j<=j+1;
if(j<7)
state<=S1;
else begin
state<=S0;
done<=1;
add<=0;
end
end
endcase
end
always # (posedge macc_clear) begin
Cin <= 8*j + i;
c <= macc_out;
end
endmodule
module mac(clk, macc_clear, A, B, macc_out, add);
input clk, macc_clear;
input signed [7:0] A, B;
input add;
output reg signed [18:0] macc_out;
reg signed [18:0] MAC;
always #( posedge clk) begin
if (macc_clear) begin
macc_out <= MAC;
MAC<=0;
end
else if (add) begin
MAC<=(A*B)+ MAC;
macc_out<=MAC;
end
end
endmodule
module ram_A( clk, addr,q);
output reg[7:0] q;
input [5:0] addr;
input clk;
reg [7:0] mem [0:63];
initial begin
$readmemb("ram_a_init.txt", mem);
end
always #(posedge clk) begin
q <= mem[addr];
end
endmodule
module ram_C(clk,addr, q);
input [18:0] q;
input [5:0] addr;
input clk;
reg [18:0] mem [0:63];
always #(posedge clk) begin
mem[addr] <= q;
end
endmodule
ModelSim Functional Simulation Wave Form
1) Take a look at the schematic view for your MACC module - I think some of your "problems" will be obvious from that;
2) Consider using an always#(*) (Combinational) block for your FSM control signals (stuff like add or macc_clear) rather than a always#(posedge clk) (sequential) - it makes the logic to assert them easier. Right now they're registered, so you have a cycle delay. ;
3) In your MAC, you clear the MAC register on a reset, but you don't clear the macc_out register.
In short, I think you need to step back, and consider which signals are combinational logic, and which ones are sequential and need to be in registers.

Verilog code does not print desired output

Can you tell me why this simple verilog program doesn't print 4 as I want?
primitive confrontatore(output z, input x, input y);
table
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive
comparatore :
module comparatore (r, x, y);
output wire r;
input wire [21:0]x;
input wire [21:0]y;
wire [21:0]z;
genvar i;
generate
for(i=0; i<22; i=i+1)
begin
confrontatore t(z[i],x[i],y[i]);
end
endgenerate
assign r = & z;
endmodule
commutatore :
module commutatore (uscita_commutatore, alpha);
output wire [2:0]uscita_commutatore;
input wire alpha;
reg [2:0]temp;
initial
begin
case (alpha)
1'b0 : assign temp = 3;
1'b1 : assign temp = 4;
endcase
end
assign uscita_commutatore = temp;
endmodule
prova:
module prova();
reg [21:0]in1;
reg [21:0]in2;
wire [2:0]uscita;
wire uscita_comparatore;
comparatore c(uscita_comparatore, in1, in2);
commutatore C(uscita, uscita_comparatore);
initial
begin
in1 = 14;
$dumpfile("prova.vcd");
$dumpvars;
$monitor("\n in1 %d in2 %d -> uscita %d uscita_comparatore %d \n", in1, in2, uscita, uscita_comparatore);
#25 in2 = 14;
#100 $finish;
end
endmodule
The issue is in commutatore. You are using initial, which means the procedural block is only executed at time 0. At time 0, the input alpha is 1'bx, meaning temp is not assigned to anything. Instead of initial, use always #* which will execute the procedural block every time alpha changes.
Generally you should not assign statements in procedural blocks. It is legal Verilog however it is often the source of design bugs and synthesis support is limited.
always #*
begin
case (alpha)
1'b0 : temp = 3;
1'b1 : temp = 4;
default: temp = 3'bx; // <-- optional : to catch known to unknown transitions
endcase
end
The reason you are not getting 4 as you expect for an output is because your commutatore uses an initial block with assign statements in it when you wanted an always #* block to perform the combinational logic to get temp. initial blocks only fire once at the beginning of a simulation, while you want continuous assignment to act as combinational logic. Also, the assign statements in the block are not needed, they only make the simulation behave improperly for your purposes (typically, you will never need to use assign inside another block (initial,always,etc) as this has another meaning than simply set x to y.
For example, you really want something like this:
always #(*) begin
case (alpha)
1'b0: temp = 3'd3;
1'b1: temp = 3'd4;
endcase
end
Also, Verilog already has a build XNOR primative so your confrontatore is not needed, you can use xnor instead.

Changing freq of triangle waveform verilog

So I've already got my triangle waveforms, now i want to change the frequency of it, but i'm getting errors and i don't know what's the actual problem.
module sxoc(clk,res,out1,freq,count);
input clk,res;
input [0:7]freq;
output [0:7]count;
output [0:7]out1;
reg [0:7]out1;
always #(posedge clk)
begin
if (res)
begin
out1=8'b00000000;
count=8'b00000000;
end
else
count =count + 1;
if (count == freq)
if(out1<=256)
begin
out1=out1 + 1;
count = 0;
end
end
endmodule
module atam_test;
reg clk,res;
reg [0:7]freq;
wire [0:7]count;
wire [0:7]out1;
sxoc sxoc1(clk,res,out1,freq,count);
always #2 clk=~clk;
initial
begin
clk=0;res=1;freq=8'b00000011;
#5 res=0;
end
initial #5000 $finish;
endmodule
Procedural assignments (in an always block) can only be made to a reg. Change:
output [0:7]count;
to:
output reg [0:7]count;

verilog average, add n-bit numbers together and then divide by nbit numbers

I am having trouble putting this code together my main code is a state machine it adds 2 numbers together = sum then loads A to add A to sum(sum=a+sum) after clock is reached it then divides by n bit. I'm lost putting it together. In having Lots of trouble assigning outputs. what is legal and what is not am I able to set the regs equal to each other sometimes I feel like I can do that and some other times I cannot.if I use the module can the input be an output and vice versa I posted my whole code cause I wanted to get it to work. I think my device is correct but I need to create a test bench to tested.
module Adder (A1, B1, Cin,Q);
parameter n = 5;
output[n:0]Q;
reg [n:0]Q;
input [n:0] A1;
wire[n:0] A1;
input [n:0] B1;
wire [n:0] B1;
input Cin;
always #(A1 or B1 or Cin)
begin
Q = A1 +B1 + Cin;
end
endmodule
module ave(Clk,X,LA,DataA,Sum,Q);
parameter n=5;
input A,B,EB,Temp,DataA,DataB,Sum,Q;
input X;
reg A,B,Temp,Sum;
reg y,Y
wire
reg S1=3'b000;S2=3'b001;S3=3'b010;S4=3'b011;S5=3'b100;
always (Clk)
begin
case(y)
S1:
y=S2;
S2:
y=S3;
S3:
if (counter>0) y=S2;
else y=S4;
S4:
y=S4;
S5:
Done;
endcase
end
always (Clk)
begin
case
S1:
Counter=n; Temp=n; Sum=0;
S2:
A=X;
S3:
if (counter>0) B<=A+B;
else B<=B;
S4:
DataA=Temp;
DataB=Sum;
S5:
Done=1;
end
Adder add(A,Sum,Cin,Sum);
divider divid(Clk,1,1,1,1,DataA,DataB,1,1,Q,0);
endmodule
this is my divider plus the other modules:
module shiftlne(R,C,L,w,Clk,Q);
parameter n=8;
input [n-1:0]R;
input L,w,Clk,C;
output [n-1:0]Q;
reg [n-1:0]Q;
integer k;
always #(posedge Clk)
begin
if(L)begin
if(C)begin
Q<=R;end
else
begin
for (k=0;k<(n-1);k=(k+1))
Q[k+1]=Q[k];
Q[0]<=w;
end
end
end
endmodule
module downcounter (R,E,L,Clk,Q);
parameter n=8;
input[n-1:0]R;
input Clk,L,E;
output [n-1:0]Q;
reg[n-1:0]Q;
always #(posedge Clk)
begin if(L)
Q<=R;
else if(E)
Q<=(Q-1);
end
endmodule
module muxdff( D0, D1, Sel, Clk,Q);
input Clk,D0,D1,Sel;
wire D;
output Q;
reg Q;
assign D=Sel?D1:D0;
always # (posedge Clk)
begin
Q=D;
end
endmodule
module regne (R,Clk,Resetn,E,Q);
parameter n=8;
input [n-1:0]R;
input Clk,Resetn,E;
output [n-1:0]Q;
reg [n-1:0] Q;
always #(posedge Clk or negedge Resetn)
begin
if (Resetn==0)
Q<=0;
else if (E)
Q<=R;
end
endmodule
Are you stuck using Verilog-95 if not you can clean up the code style, if nothing else it helps spot the bugs easier.
NB: Uses spaces to indent your code, not tabs as they mess up the formatting when posting Q's and can look different to people review your code depending on how there editor is setup.
module Adder #(
parameter n = 5
)(
input [n:0] A1, //Inputs do not have to be declared as wires
input [n:0] B1,
input Cin,
output reg [n:0] Q;
);
//Auto sensitivity list with #* lowers chance of bugs
always #* begin
Q = A1 + B1 + Cin;
end
endmodule
Most languages, and I apply this to my verilog keep constants like parameters and localparam in UPPERCASE, everything else is lowercase.
Your shiftlne code be made more readable: readable code to me implies easier to spot the bugs and understand the design intention.
always #(posedge Clk) begin
if( L ) begin
if( C ) begin
Q <= R;
end
else begin
for (k=0;k<(n-1);k=(k+1))
Q[k+1] = Q[k]; //For loop only applies to this line
// should it not be Q[k+1] <= Q[k];
Q[0] <= w;
end
end
end
endmodule

how to map reg values to the ports of other module

i am an amateur in verilog. i am trying to call module divider. but i get errors like "Reference to vector reg 'qtnt' is not a legal net lvalue" in synthesis. i have tried using wires as inputs but when i tried to assign values to them an error message was recieved. please help
module euclid_mul(
input[9:0] p0,p1,q0,
input[19:0] tot,
input clk,
output reg [20:0] p2,
output reg out_en,o1,o2
);
reg[20:0] dvr,dvd,qtnt,rem;
reg[9:0] ph;
reg[20:0] mul,res;
reg enable,f1;
initial f1=0;
initial enable=0;
divider div2(dvd,dvr,enable,qtnt,rem,f1);
always # (negedge clk)
begin
if(f1==0) begin
mul=q0*p1;
ph=p0;
res={11'b00000000000,ph[9:0]}-mul;
if(res[20])
begin
o1=1;
dvd=-res;
end
else
dvd=res;
o2=1;
dvr=tot;
enable=1;
end
end
always #(posedge f1)
begin
if(res[20])
begin
p2=tot-rem;
out_en=1;
end
else
begin
p2=rem;
out_en=1;
end
end
endmodule
You may get more response if you formatted the code so that it was easier to read. Something like the following:
I have also pointed out a section where I think you are missing a begin and end statement.
Also inside clocked sections you often want to use nonblocking assignments <=.
Since you have not provided the divider module, I would prefer to see ports named rather than specified in order, it might help us to know what it is likely to do, even better label it with its direction and width.
module euclid_mul(
input [9:0] p0,p1,q0,
input [19:0] tot,
input clk,
output reg [20:0] p2,
output reg out_en,o1,o2
);
reg [20:0] dvr,dvd,qtnt,rem;
reg [9:0] ph;
reg [20:0] mul,res;
reg enable,f1;
initial begin
f1 = 0;
enable = 0;
end
divider div2(dvd,dvr,enable,qtnt,rem,f1);
// My prefered style to help us understand conectivity.
//divider
// divider_i0(
// .divisor( dvd ), //input [20:0]
// .result ( res ) //output [20:0]
//);
always # (negedge clk) begin
if(f1==0) begin
mul = q0*p1;
ph = p0;
res = {11'b00000000000,ph[9:0]}-mul;
if ( res[20] ) begin
o1 = 1;
dvd = -res;
end
else begin //There was a missing begin
dvd = res;
o2 = 1;
dvr = tot;
enable = 1;
end //Missing End
end
end
always #(posedge f1) begin
if(res[20]) begin
p2 = tot-rem;
out_en = 1;
end
else begin
p2 = rem;
out_en = 1;
end
end
endmodule
Inputs can be regs and driven from inside always or initial blocks, or wires driven from a single assign or another modules output.
Outputs should always be connected to wires, the module drives them.

Resources