Why are the outputs not changing/not getting loaded in my single cycle architecture implementation? - verilog

I've written the code for the single cycle MIPS Architecture which implements add, sub, multiply and divide. There's a 2D Reg array, A control unit, an ALU. I think I've written it all right, but the opcode I've put in the test bench doesn't seem to be going into the process: the outputs aren't changing at all and I can't understand why. Can anyone tell me why?
////////////////////////////////////////////fixed
module registermemory(
input [3:0]Ra, Rb, Wa, Wd,
input write, input clk,
output [3:0] A,B
);
reg [15:0] memarray [3:0];
integer i;
initial begin
for(i=0;i<=15;i=i+1)
memarray[i]<=4'b0101; ///when the entire 2D array has same value?
end
integer r1,r2,w1;
always#(clk)
begin
r1=Ra;r2=Rb;w1=Wa;
end
assign A = memarray[r1];
assign B = memarray[r2];//assign used outside always. equal to used inside always.
always#(Wd)
begin
if(write)
memarray[w1]=Wd;
end
endmodule
///////////////////////////////
module controlblock(opcode,cntrl,Ra,Rb,Wa,write);
input [13:0]opcode;
output reg[1:0]cntrl;
output reg[3:0]Ra;
output reg[3:0]Rb;
output reg[3:0]Wa;
output reg write; //control signal tells that register has to be written in reg file
always#(opcode) ///why #opcode tho?
begin
cntrl=opcode[13:12];
Ra=opcode[11:8];
Rb=opcode[7:4];
Wa=opcode[3:0];
write=1; //why tho?
end
endmodule
///////////////////////////////
module alu_arith(input[3:0]A, input[1:0] cntrl,
input clk,
input[3:0]B,
output reg[3:0]Wd
);
always#(clk)
begin
case(cntrl)
00:Wd=A+B;
01:Wd=A-B;
10:Wd=A*B;
11:Wd=A/B;
default: Wd=4'b0000;
endcase
end
endmodule
///////////////////////////////////////////////////////
module concat(input [0:13]opcode, input clk, output[3:0]Wd);
wire[3:0]Ra;wire[3:0]Rb;wire[3:0]Wa;wire written;wire[1:0]cntrl;
wire[3:0]A;wire[3:0]B;wire[3:0]Wd;
controlblock a1(opcode,cntrl,Ra,Rb,Wa,write); //
registermemory a2(Ra, Rb, Wa, Wd,write,clk,A,B
); //
alu_arith a3(A,cntrl,clk,B,Wd); //
endmodule
//////////////////////////////////////////////////////////////
module testbench;
reg clk;
reg[13:0]opcode;
wire[3:0]Wd;
wire[1:0] cntrl;
reg[3:0]A,B;
concat a4(opcode,clk,Wd);
initial
clk=0;
always
#2 clk=!clk;
initial begin
$display("\ttime \tclk \tcntrl \tA \tB \tWd ");
$monitor("%d,\t \t%b \t%b \t%b \t%b \t%b",
$time, clk, cntrl, A, B, Wd);
#10 opcode=14'b00010010110100;
#20 opcode=14'b01100010101010;
end
initial
#50 $finish;
endmodule

You declared memarray incorrectly as a 16-bit wide by 4 word deep memory. You want a 4-bit wide by 16 deep:
reg [3:0] memarray [0:15];
When I make this change, I see the Wd output changing.

Related

Why is iverilog complaining about my testbench module?

I'm writing a verilog module for my CompSci class and this module specifically is the data memory module. Structurally and analytically, I'm looking at it and it should work based off of the other files that I have, but I'm not sure why this one specifically is acting up and giving me all x's. Hoping a fresh set of eyes can help find the error I missed. Thanks in advance.
datamem.v:
module datamem(Ina, Inb, enable, readwrite, dataOut, clk, rst);
input wire [31:0] Ina;
input wire [31:0] Inb;
input wire enable;
input wire readwrite;
input wire clk;
input wire rst;
reg [31:0] memory[0:65535];
output reg [31:0] dataOut;
always #(memory[Ina]) begin
dataOut = memory[Ina];
end
always #(posedge clk) begin
if(1'b1 == readwrite) begin
memory[Ina] = Inb;
end
end
endmodule
datamem_tb.v:
module datamem_tb();
reg [31:0] Ina;
reg [31:0] Inb;
reg enable;
reg readwrite;
reg clk;
reg rst;
wire [31:0] dataOut;
datamem DUT (Ina, Inb, enable, readwrite, dataOut, clk, rst);
initial
begin
Ina <= 32'd0;
Inb <= 32'd0;
enable <= 0;
readwrite <= 0;
#20 Ina <= 32'd1234;
#20 Inb <= 32'd1234;
#20 Ina <= 32'd0517;
#20 Inb <= 32'd10259;
end
always #(Ina or Inb)
#1 $display("| Ina = %d | Inb = %d | dataOut = %d |", Ina, Inb, dataOut);
endmodule
A few things as to why you are getting all 'x:
You never run the clock, you need to add something like the following to have the clock toggle:
initial begin
clk = 1'b0;
forever #5 clk = ~clk;
end
You never assert readwrite which is required to write to your memory module (you set it to 0 on line 20 and never change it). Without being written to, memory will retain its original value of 'x for every element
Aside from that, there are a few other issues with your module:
Use implicit sensitive lists (instead of always #(memory[inA]) use always #(*))
Use non-blocking assignment for your memory write (memory[inA] <= inB)
Consider using $monitor instead of $display for your print statements to avoid timing issues, and you only need call it at the beginning of your initial block in your testbench (http://referencedesigner.com/tutorials/verilog/verilog_09.php)
Your rst and enable arent connected to anything.
Another example of a memory unit implementation can be found here:
Data memory unit

4-bit counter using T-flipflop in verilog

I'm trying to design a 4-bit counter with T-flipflop, here's what i did:
1- From a D-flipflop to T-flipflop:
module T_FlipFlop( clk,T, Q);
input wire clk;
input wire T;
output reg Q;
wire D;
initial
begin
Q<=1'b0;
end
assign D= T ^ Q;
always #(negedge clk)
begin
Q<=D;
end
endmodule
with RTL shematic :
following this "D_ff to T_ff" conversion:
2- Then, i instantiated 4 T-flipflops in the top module and connected the output of each flipflop to the clk of the next one:
module Counters_FreqDividers( sysclk,Q1,Q2,Q3,Q4);
input sysclk;
output wire Q1;
output wire Q2;
output wire Q3;
output wire Q4;
T_FlipFlop num_1(.clk(sysclk),.T(1'b1),.Q(Q1));
T_FlipFlop num_2(.clk(Q1),.T(1'b1),.Q(Q2));
T_FlipFlop num_3(.clk(Q2),.T(1'b1),.Q(Q3));
T_FlipFlop num_4(.clk(Q3),.T(1'b1),.Q(Q4));
endmodule
with RTL schematic :
to follow this diagram:
We know that T-flipflop is just a JK-flipflop with J and K connected to each other and that's what we have here, so consider them as T-flipflops.
3-The simulation:
4- Finally, my questions:
1) why Q1 is the ONLY output that operates properly?
2) Why Q2, Q3, Q4 starts with 1 although i have initialized them as 0?
I can't figure out what's missing, i tried to play around but nothing worked and i'm stuck here!
Edit: my testbench:
module test;
// Inputs
reg sysclk;
// Outputs
wire Q1;
wire Q2;
wire Q3;
wire Q4;
// Instantiate the Unit Under Test (UUT)
Counters_FreqDividers uut (
.sysclk(sysclk),
.Q1(Q1),
.Q2(Q2),
.Q3(Q3),
.Q4(Q4)
);
initial begin
// Initialize Inputs
sysclk <= 1'b1;
#200 $finish();
end
always #5 sysclk=~sysclk;
endmodule

Verilog logical error

module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
assign inner = dataA [3:0]*dataB [3:0];
end
else begin
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
//inner=inner1;
ooutp =s1?inner [9:0]:10'd0;
end
endmodule
This is the code. regfile is a simple register file. In the testbench, s0 = 0 during the first cycle and s0 = 1.
For subsequent cycles, this code should return the value of A*B+C*D by using one adder and one multiplier. In the first cycle, when c0 = 0, the answer that is saved in inner (a register) is right but in the second cycle, when c0 = 1 the answer is wrong.
Por example: A=1; B=2; C=1; D=1;
First cycle: x=A*B=2
Second cycle (C*D)+x=5
I think there is something wrong with this statement
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
Any help or hint will be appreciated.
Although assign can be used from within an always block, I think you just wanted to store a value into inner depending upon the value of s0. To do that, use non-blocking assignments ( <= ).
Also, you can directly output to ooutp instead of saving the final result in inner, avoiding a possible glitch in the multiplexer you instantiate here:
ooutp =s1?inner [9:0]:10'd0;
Which, by the way, it should be outside the always block, in an assign line:
assign ooutp = s1? inner [9:0]:10'd0;
module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
inner <= dataA [3:0]*dataB [3:0];
end
else begin
ooutp <= ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
end
endmodule

Why is it giving error in module part1?

In my previous question I said that I was asked to design a bottling system that fills bottles with the desired number of tablets. In part1 of my project, the user will press the button on FPGA to identify how many tablets will be put in the each bottle and the desired number will be displayed.This is the code of part 1 I have written for my project and I have no idea why it is giving errors in module part1.
module count(clk,clr,cntEn,dout);
input clk,clr,cntEn;
output reg [8:0] dout ;
always#(posedge clk)
begin
if(clr)
dout<=0;
else if(cntEn)
dout<=dout+1;
end
endmodule
module sevenseg(num,dout);
input [3:0] num;
output reg [6:0] dout;
always#(*) begin
case(num)
0:dout=7'b1111110;
1:dout=7'b1100000;
2:dout=7'b1011011;
3:dout=7'b1001111;
4:dout=7'b1100110;
5:dout=7'b1101101;
6:dout=7'b1111101;
7:dout=7'b0000111;
8:dout=7'b1111111;
9:dout=7'b1101111;
endcase
end
endmodule
module part1(clk,clr,cntEn,dout);
input clk, clr, cntEn;
output dout;
wire w1;
begin
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
end
endmodule
The error was pointed out byljk07, the begin end in module 1 are not required, some parsers might just ignore them others will throw an error. it should be:
module part1(clk,clr,cntEn,dout);
input clk, clr, cntEn;
output dout;
wire w1;
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
endmodule
I think it is also worth pointing out that unless your constrained to Verilog-95 then adopting an ANSI style port declaration is preferred, as it lead to easier to maintain code.
module part1(
input clk, clr, cntEn,
output dout
);
wire w1;
count count_1 (clk, clr, cntEn, w1);
sevenseg sevenseg_1(w1, dout );
endmodule
Module sevenseg also has an incomplete case statement which will lead to implied latches. either add a default or fully specify the output for all options of num:
module sevenseg(num,dout);
input [3:0] num;
output reg [6:0] dout;
always #(*) begin
case(num)
0:dout=7'b1111110;
1:dout=7'b1100000;
2:dout=7'b1011011;
3:dout=7'b1001111;
4:dout=7'b1100110;
5:dout=7'b1101101;
6:dout=7'b1111101;
7:dout=7'b0000111;
8:dout=7'b1111111;
9:dout=7'b1101111;
default: dout='b0;
endcase
end
endmodule

Calculating square root

I write code to calculate perfect square of number, but I am not getting proper output. I take input b and regs a, d. Firstly, I put 1 in d, then square it and store in a. Then compare with input - if it is not satisfied then increment d. But at output I am getting is square = XXXX.
My code:
module square_root(b,clk,square);
input [3:0] b;
input clk;
output [3:0]square;
reg[3:0]a,square;
reg[2:0] d;
initial
begin
d<=3'b001;
end
always#(clk)
begin
a<=d*d;
if(a==b)
square<=a;
else
d<=d+1;
end
endmodule
change this
initial
begin
d<=3'b001;
end
TO
initial
begin
d=3'b001;
end
Test Bench:
module TB_SQT;
reg [3:0]b;
reg clk;
wire [3:0]square;
square_root SQT(b,clk,square);
initial
begin
clk=0;
b=9;
end
always
#1 clk=!clk;
endmodule
module Sqrt(
input clk,
input [3:0]in,
output reg [3:0]out);
reg [3:0]temp=1;
always#(posedge clk)
begin
if((temp*temp)==in)
out<=temp;
else
temp<=temp+1;
end
endmodule
Test Bench:
module TB_Sqrt;
reg clk;
reg [3:0]in;
wire [3:0]out;
Sqrt SQRT(clk,in,out);
initial
begin
clk=0;
in=9;
end
always
#2 clk=!clk;
endmodule
Not probably the best code...but hey

Resources