Verilog sequential multiplier - verilog

I am trying to implement a 4 bit signed sequential multiplier. I have a for loop in my TB, but only the multiplicand changes, not the multiplier. When I manually change the multiplier, I notice that my product outputs all 0s then it changes to the actual product. What am I doing wrong?
module seq4bit(a,b,sign,clk,out,ready);
input [3:0]a,b;
output [7:0]out;
input ready,sign,clk;
reg [7:0] out,out_t;
reg[3:0]b0,msb,lsb;
reg[7:0]a0;
reg neg;
reg[2:0]bit;
wire ready = !bit;
initial bit = 0;
initial neg = 0;
always #(posedge clk)
if(ready)begin
bit = 3'b100;
out = 0;
out_t = 0;
a0 = (!sign || !a[3])?{4'd0,a}:{4'd0,!a + 1'b1};
b0 = (!sign || !b[3])? b : !b + 1'b1;
neg = sign && ((b[3] && !a[3])||(b[3]&&a[3]));
end
else if(bit > 0)begin
if(b0 == 1'b1)
out_t = out_t + a0;
out = (!neg)?out_t:(~out_t + 1'b1);
b0 = b0 >> 1;
a0 = a0 << 1;
bit = bit - 1'b1;
end
endmodule
module seq4tb;
reg[3:0]a,b;
wire [7:0]out;
reg clk,sign,ready;
integer i;
seq4bit uut(.a,.b,.out,.ready,.clk,.sign);
initial begin
a = 0;
b = 0;
clk = 0;
sign = 0;
ready = 1;
end
always #10 clk = ~clk;
initial
$monitor("time = %2d, a=%4b, b=%4b, sign=%1b, out=%8b, clk = %1b,ready = %1b", $time,a,b,sign,out,clk,ready);
always #(*)
begin
for ( i=0; i< 16*16 ; i = i + 1 )
#20 a = a + 1;b = b +1;
#1000 $stop;
end
endmodule

I think the main problem was that b = b + 1; was not inside the for loop.
Replace the always block in the testbench with this initial block:
initial begin
for ( i=0; i< 16*16 ; i = i + 1 ) begin
#20 a = a + 1;
b = b + 1;
end
#1000 $finish;
end
The always block simulated like an infinite loop for me. In this case, b also changes.

Related

Verilog if statement inconsistency

I'm trying to write a simple 4-bit stack of depth 8 with push/pop signals but it's behaving in a very odd manner. One of my if statements works fine and the other one does not run at all. Here's my code:
module Stack_8x4(
input wire clk,
input wire reset,
input wire push,
input wire pop,
input wire [3:0] data_in,
output reg [3:0] data_out,
output reg empty,
output reg full
);
reg [3:0] index;
reg [3:0] stack [7:0];
always #(posedge reset) begin
index <= -1;
data_out = 4'd0;
empty = 1;
full = 0;
end
always #(posedge clk) begin
if (push & !pop) begin
empty = 0;
if(!full) begin
index = index + 1;
stack[index] = data_in;
if(index > 6) full = 1;
end
end
if (pop & !push) begin
full = 0;
if(!empty) begin
data_out = stack[index];
index = index - 1;
if(index < 0) empty= 1;
end else data_out = 0;
end
end
endmodule
As you can see, the logic for push and pop is almost the same. My question is why does the line if(index < 0) empty= 1; does not work while if(index > 6) full = 1; works just fine?
Here's a test bench and simulation for more details:
module sim();
reg clk;
reg reset;
reg push;
reg pop;
reg [3:0] data_in;
wire [3:0] data_out;
wire full;
wire empty;
//wire [3:0]i;
always begin
clk = 0;
#5
clk = 1;
#5
clk = 0;
end
initial begin
// setup
reset = 1;
push = 0;
pop = 0;
data_in = 0;
#10
reset = 0;
// idle
#20
// push 1, 2, 3, 4, 5, 6, 7, 8, 9 to fill the module and test for idling at full
push = 1;
data_in = 1;
#10
data_in = 2;
#10
data_in = 3;
#10
data_in = 4;
#10
data_in = 5;
#10
data_in = 6;
#10
data_in = 7;
#10
data_in = 8;
#10
data_in = 9;
#10
data_in = 10;
#10
data_in = 11;
#10
pop = 1;
#10
push = 0;
#30
pop = 0;
push = 1;
#30
push = 0;
#20
pop = 1;
// pop
//pop = 1;
end
Stack_8x4 S (
.clk(clk),
.push(push),
.pop(pop),
.reset(reset),
.data_in(data_in),
.data_out(data_out),
.full(full),
.empty(empty)
);
endmodule
Your main issue is in the attempt to use signed data with unsigned variables. So, index <= -1;, index < 0 just do not work as you expect. My suggestion is to forget about signed arithmetic and do unsigned only.
Other issues:
you should use only a single always block to do reset and non-reset work.
you should use non-blocking assignments everywhere in your always #posedge blocks
for some reason you do not use 2 elements in your stack (6, 7) due to 'index < 6'.
So, here is my re-write of your code:
always #(posedge clk) begin
if (reset) begin
index <= 0;
data_out <= 4'd0;
empty <= 1;
full <= 0;
end
else if (push & !pop) begin
if(index < 8) begin
full<= 0;
stack[index] <= data_in;
index <= index + 1;
end
else
full <= 1;
end
else if (pop & !push) begin
if(index == 0) begin
empty <= 1;
data_out <= 0;
end
else begin
empty <= 0;
index <= index - 1;
data_out <= stack[index];
end
end // if (pop & !push)
end // always # (posedge clk)

Mips DataMemory with Verilog

I'm trying to make MIPS Data Memory with Verilog.
The code does not work properly. It is unable to read and write as of right now. I thought the code that I made is correct, but if there is any flaw in here, please make it work. The code below is what I made and used.
//WORD_LEN = 32
//MEM_CELL_SIZE = 8
//DATA_MEM_SIZE = 1024
module DataMemory(CLK, rst, Addr, WriteData, ReadData, MemRead, MemWrite);
input CLK, rst;
input MemRead, MemWrite; //switch
input [`WORD_LEN-1:0] Addr, WriteData;
output reg[`WORD_LEN-1:0] ReadData;
reg [`MEM_CELL_SIZE-1:0] DataMem [0:`DATA_MEM_SIZE];
wire [`WORD_LEN-1:0] Pointer;
integer i;
always #(negedge CLK) //Write on memory needs CLK
begin
if(rst)
for (i = 0; i < `DATA_MEM_SIZE; i = i + 1)
DataMem[i] <= 0;
/*
// Identify each DataMem
*/
else if(MemWrite == 1 && MemRead == 0) // Store Word
{DataMem[Pointer], DataMem[Pointer+1], DataMem[Pointer+2], DataMem[Pointer+3]} <= WriteData;
else if(MemWrite == 0 && MemRead == 1) // Load Word
ReadData <= ((Addr >= 1024) ? 0 : {DataMem[Pointer], DataMem[Pointer+1], DataMem[Pointer+2], DataMem[Pointer+3]});
end
// Pointer must be added 4 shifter >>2 << 2 helps to flush 1~3
assign Pointer = (Addr >> 2) << 2;
endmodule
And Testbench which I use below here.
`include "Defines.v"
//WORD_LEN = 32
//MEM_CELL_SIZE = 8
//DATA_MEM_SIZE = 1024
module DataMemoryTest;
reg CLK, rst;
reg MemRead, MemWrite;
reg [`WORD_LEN-1:0] Addr, WriteData;
wire [`WORD_LEN-1:0]ReadData;
DataMemory TestDataMemory(.CLK(CLK), .rst(rst), .Addr(Addr), .WriteData(WriteData),
.ReadData(ReadData), .MemRead(MemRead), .MemWrite(MemWrite));
initial begin
CLK = 1;
repeat(5000) #50 CLK = ~CLK;
end
initial begin
rst = 1;
#100;
MemRead = 0;
MemWrite = 1;
Addr = 32'd0;
WriteData = 32'd123;
#100;
MemRead = 0;
MemWrite = 1;
Addr = 32'd4;
WriteData = 0;
#100;
MemRead = 0;
MemWrite = 1;
Addr = 32'd8;
WriteData = 32'd17;
#100;
MemRead = 1;
MemWrite = 0;
Addr = 32'd12;
WriteData = 32'd123;
#100;
MemRead = 1;
MemWrite = 0;
Addr = 32'd16;
WriteData = 0;
#100;
MemRead = 1;
MemWrite = 0;
Addr = 32'd20;
WriteData = 32'd17;
end
endmodule
The testbench keeps the design in reset. You need to set rst=0 after some delay.
initial begin
rst = 1;
#500;
rst = 0;
#100;
MemRead = 0;
MemWrite = 1;
Addr = 32'd0;
WriteData = 32'd123;

Programming help for Verilog beginner. Debugging in ISE

I have experience in VHDL and SystemC, and now I'm training to learn Verilog, but I'm having trouble getting started.
I'm currently trying to make a 8 bit adder.
module alu(
input [7:0] a,
input [7:0] b,
input clk,
input op,
output reg [7:0] out,
output reg overflow
);
integer myA;
integer myB;
always #(negedge clk)
begin
myA = a;
myB = b;
overflow = 0;
if (op == 0) begin
//Subtract
out = myA - myB;
if (myA - myB <0) begin
overflow = 1;
end
end
else begin
//Add
out = myA + myB;
if (myA + myB > 255) begin
overflow = 1;
end
end
end
endmodule
But in testing it doesn't work properly.
I used ISE to generate a test bench, and since I don't know how to setup a clock, I set it up manually:
// Add stimulus here
a = 255;
b = 45;
clk = 1;
op = 1;
#100
clk = 0;
// Add stimulus here
a = 0;
b = 255;
clk = 1;
op = 1;
#100
clk = 0;
// Add stimulus here
a = 255;
b = 0;
clk = 1;
op = 0;
#100
clk = 0;
// Add stimulus here
a = 90;
b = 45;
clk = 1;
op = 1;
#100
clk = 0;
The last instruction, 45+90 gives me the correct result, but every other result gives me 0.
I've tried several variations of the main if, but there always errors in the output.
if (op == 0) begin
out = a + b;
if (myA-myB <0) begin
//overflow
out = 7;
end
end else begin
out = a-b;
if (myA+myB>255) begin
//overflow
out = 8;
end
end
Here's the full test bench code. Edited to include #100 between clk = 0 and clk = 1.
`timescale 1ns / 1ps
module a;
// Inputs
reg [7:0] a;
reg [7:0] b;
reg clk;
reg op;
// Outputs
wire [7:0] out;
// Instantiate the Unit Under Test (UUT)
alu uut (
.a(a),
.b(b),
.clk(clk),
.op(op),
.out(out)
);
initial begin
// Initialize Inputs
a = 0;
b = 0;
clk = 0;
op = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
a = 55;
b = 45;
clk = 1;
op = 1;
#100
clk = 0;
#100
// Add stimulus here
a = 255;
b = 45;
clk = 1;
op = 1;
#100
clk = 0;
#100
// Add stimulus here
a = 0;
b = 255;
clk = 1;
op = 1;
#100
clk = 0;
#100
// Add stimulus here
a = 255;
b = 0;
clk = 1;
op = 0;
#100
clk = 0;
#100
// Add stimulus here
a = 90;
b = 45;
clk = 1;
op = 1;
#100
clk = 0;
#100
end
endmodule
#X in Verilog means "delay X time steps before continuing". So in your code
#100
clk = 0;
// Add stimulus here
a = 255;
b = 0;
clk = 1;
there's no delay between the clock going low and going high again, which might be your problem. Try adding a #100 somewhere between clk = 0; and clk = 1;
Just a tip. I think in most cases the clock is created in an always block and then the inputs are changed in another initial block so
always begin
#5 clk = ~ clk; // here the clock period is 10
end
initial begin
clk = 0;
a = 255;
b = 45;
op = 1;
#10;
a = 90;
b = 45;
op = 1;
end

Verilog :errors.Invalid use of input signal <ck> as target

I can't figure out , where this errors.Invalid use of input signal <ck> as target error is coming from?
module register
#(parameter Width = 8)
(output reg [Width-1:0] out,
input [Width-1:0] in,
input clear, load, clock);
always #(posedge clock)
if (~clear)
out<= 0;
else if (~load)
out<=in;
endmodule
module adder
#(parameter Width = 8)
(input [Width-1:0] a,b,
output [Width-1:0] sum);
assign sum = a + b;
endmodule
module compareLT // compares a < b
#(parameter Width = 8)
(input [Width-1:0] a, b,
output out);
assign out = a < b;
endmodule
module compareLEQ // compares a <= b
#(parameter Width = 8)
(input [Width-1:0] a, b,
output out);
assign out = a <= b;
endmodule
module roshanpoop
#(parameter Width = 8)
(input ck, reset,
input [Width-1:0] yln,
output [Width-1:0] y, x);
wire [Width-1:0] i, addiOut, addxOut;
wire yLoad, yClear, xLoad, xClear, iLoad,iClear;
register #(Width) I (i, addiOut, iClear, iLoad, ck);
register #(Width) Y (y, yIn, yClear, yLoad, ck);
register #(Width) X (x, addxOut, xClear, xLoad, ck);
adder #(Width) addI (addiOut, 'b1, i),
addX (x, y, addxOut);
compareLT #(Width) cmpX (x, 'b0, xLT0);
compareLEQ #(Width) cmpI (i, 'd10, iLEQ10);
fsm ctl (xLT0,iLEQ10 ,yLoad, yClear, xLoad, xClear, iLoad,iClear, ck, reset);
endmodule
module fsm
(input LT,LEQ, ck, reset,
output reg yLoad, yClear, xLoad, xClear, iLoad, iClear);
reg [2:0] cState, nState;
always #(posedge ck,negedge reset)
if (~reset)
cState <= 0;
else
cState <= nState;
always#(cState, LT,LEQ)
case (cState)
3'b00: begin //stateA
yLoad = 1; yClear = 1; xLoad = 1; xClear = 0;
iLoad = 1; iClear = 0; nState = 3'b001;
end
3'b001: begin // state B
yLoad = 1; yClear = 1; xLoad = 0; xClear = 1;
iLoad = 0; iClear = 1; nState = 3'b010;
end
3'b010: begin //state C
yLoad = 1; yClear = 1; xLoad = 1; xClear = 1;
iLoad = 1; iClear = 1;
if(LEQ) nState = 3'b001;
if(~LEQ & LT) nState = 3'b011;
if (~LEQ & ~LT) nState = 3'b100;
end
3'b011: begin //state D
yLoad = 1; yClear = 0; xLoad = 1; xClear = 1;
iLoad = 1; iClear = 1; nState = 3'b101;
end
3'b100: begin //state E
yLoad = 1; yClear = 1; xLoad = 1; xClear = 0;
iLoad = 1; iClear = 1; nState = 3'b101;
end
default: begin // required to satisfy combinational synthesis rules
yLoad = 1; yClear = 1; xLoad = 1; xClear = 1;
iLoad = 1; iClear = 1;nState = 3'b000;
$display("Oops, unknown state: %b", cState);
end
endcase
endmodule
error:
line no:70
Invalid use of input signal ck as target,
Invalid use of input signal target as target.
In module roshanpoop above mentioned error are coming . what might be the problem ?
The error is caused by this instantiation:
fsm ctl (xLT0,iLEQ10 ,yLoad, yClear, xLoad, xClear, iLoad,iClear, ck, reset);
of the module:
module fsm
(input LT,LEQ, ck, reset,
output reg yLoad, yClear, xLoad, xClear, iLoad, iClear);
You are using positional instantiation, which is not recomended, because it makes the task of maintaining your module more difficult (think, for example, if you want to add signals to your module: if you add it in the middle of the module's definition, all remaining signals will be wrongly connected).
Here, the use of positional instantiation has caused signal ck from the top module to be connected to iLoad, which is an output signal from fsm, so you are trying to put a value to a input only signal ck.
The way to have it right is to use explicit instantiation, where each signal from the module is explicitly named and assigned to a signal from the top module, like this:
fsm ctl (.LT(xLT0),
.LEQ(iLEQ10),
.yLoad(yLoad),
.yClear(yClear),
.xLoad(xLoad),
.xClear(xClear),
.iLoad(iLoad),
.iClear(iClear),
.ck(ck),
.reset(reset)
);
So, regardless of where in the argument list you put signal clk it will be always connected to the right signal inside the module.
Not an answer but some tips on potentially making the code easier to understand. I would post as a comment but code examples do not work well in comments.
1) Manual sensitivity lists can [should] be avoided when using a modern toolset.
always#(cState, LT,LEQ)
With an automatic sensitivity list would just be:
always #(*)
// Or
always #*
If you are able to use SystemVerilog (as question tags indicate) then the preferred method is :
always_comb
2) Instead of:
yLoad = 1; yClear = 1; xLoad = 1; xClear = 0;
iLoad = 1; iClear = 0;
For every case, we could have
reg [5:0] temp_control;
assign {yLoad, yClear xLoad, xClear, iLoad, iClear} = temp_control;
//...
always #*
case(cState)
3'b000: begin //stateA
temp_control = 6'b111010; nState = 3'b001;
end
3'b001: begin // state B
temp_control = 6'b110101; nState = 3'b010;
end
3'b010: begin //state C
temp_control = 6'b111111;
if(LEQ) nState = 3'b001;
if(~LEQ & LT) nState = 3'b011;
if (~LEQ & ~LT) nState = 3'b100;
end
//...
Better still create Mnemonics for the temp_controls.
localparam [5:0] CTRL_LOAD = 6'b111010;
localparam [5:0] CTRL_CLEAR = 6'b111010;
Mnemonics for the states are also really helpful:
localparam [2:0] STATE_INIT = 3'b000;
localparam [2:0] STATE_START = 3'b001;
localparam [2:0] STATE_STOP = 3'b010;
The the FSM structure might look some thing like:
always #*
case(cState)
STATE_INIT: begin //stateA
temp_control = CTRL_LOAD; nState = STATE_START;
end
STATE_START: begin // state B
temp_control = CTRL_CLEAR; nState = STATE_STOP;
end
STATE_STOP: begin //state C
temp_control = CTRL_HALT;
if(LEQ) nState = STATE_START;
if(~LEQ & LT) nState = STATE_RECYCLE;
if (~LEQ & ~LT) nState = STATE_CRUSH;
end
As the readability improves it is often easier to spot an incorrectly used signal.

Verilog not displaying output

I have a homework problem where I'm supposed to create a module for single-precision IEEE-754 floating point multiplication. This is the module:
module prob3(a, b, s);
input [31:0] a, b; // operands
output reg [31:0] s; // sum - Could potentially use wire instead
integer i; // loop variable
reg [8:0] temp;
reg [47:0] intProd; // intermediate product
reg [23:0] tempA;
reg [23:0] tempB;
initial begin
//Initialization
for (i = 0; i < 48; i = i + 1) begin
intProd[i] = 0;
end
//Compute the sign for the result
if (a[31]^b[31] == 0) begin
s[31] = 0;
end
else begin
s[31] = 1;
end
//Compute the exponent for the result
#10 temp = a[30:23] + b[30:23] - 8'b11111111;
//Case for overflow
if(temp > 8'b11111110) begin
s[30:23] = 8'b11111111;
for (i = 0; i < 23; i = i + 1) begin
s[i] = 0;
end
$finish;
end
//Case for underflow
else if (temp < 8'b00000001) begin
for (i = 0; i < 31; i = i + 1) begin
s[i] = 0;
end
$finish;
end
else begin
s[30:23] = temp[7:0];
end
//Mutliply the signficands
//Make implicit one explicit
tempA[23] = 1;
tempB[23] = 1;
//Make operands 24 bits
for(i = 0; i < 23; i = i + 1) begin
tempA[i] = a[i];
tempB[i] = b[i];
end
//Compute product of signficands
intProd = tempA * tempB;
//Check and see if we need to normalize
if(intProd[47:46] >= 2'b10) begin
intProd = intProd >> 1;
temp = s[30:23] + 1'b1;
if(temp > 8'b11111110) begin
s[30:23] = 8'b11111111;
for (i = 0; i < 23; i = i + 1) begin
s[i] = 0;
end
$finish;
end
else
s[30:23] = temp[7:0];
end
s[22:0] = intProd[47:25];
end
endmodule
Here is my testbench:
module prob4;
reg [31:0] a, b;
wire [31:0] s;
// instantiate the floating point multiplier
prob3 f1(a, b, s);
initial begin
assign a = 32'h42055555;
assign b = 32'hBDCCCCCD;
#10 $monitor("s = %h", s);
assign a = 32'hBF555555;
assign b = 32'hCAB71B00;
#10 $monitor("s = %h", s);
a = 32'hFF500000;
b = 32'h7E700000;
#10 $display("s = %b", s);
a = 32'h01700000;
b = 32'h02F00000;
#10 $display("s = %b", s);
a = 32'hBE000000;
b = 32'h455F36DB;
#10 $display("s = %b", s);
a = 32'h3C800000;
b = 32'h3A800000;
#10 $display("s = %b", s);
a = 32'hC797E880;
b = 32'hB7FBA927;
#10 $display("s = %b", s);
end
endmodule
It displays the first value of s, but that is it. I'm honestly not too familiar with Verilog, so any clarification on why this might be happening would be truly appreciated.
The reason you are seeing only a single value for s is because all of your floating point logic (all the stuff in the prob3 module) is inside an initial block. Thus, you only run that code once; it starts at time 0, has a pause for 10 time units and finishes; never to run again. Here are a few tips for implementing the unit (assuming the module is suppose to be synthesizable and not just a functional verification model):
Place your combinational logic in an always #(*) block, not an initial block.
As toolic mentioned, only call $monitor once, and it will inform you whenever s or any other variables given as arguments change; thus you do not need the $display statements either unless you want to know the value of s at that point of execution (whether it changed or not and inline with the processes, so not necessarily the final value either). So typically your testbench main stimulus initial block would have $monitor() as the first line.
Don't call $finish inside your logic; ideally, you should set an error signal instead that the testbench might then choose to call $finish if it sees that error signal asserted.
Don't use assign inside procedural blocks (always, initial, etc), just say a = ... not assign a = ...

Resources