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
Related
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.
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
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.
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
My code for the design block and the testbench compiles; however, when I simulate, I'm not getting the correct output. Can anyone tell me where I'm going wrong in my code?
Here is the code for testbench:
module testbench;
reg [511:0]FROM_LS;
reg CLK;
reg [63:0]TO_IF_ID;
initial
begin
CLK= 0;
TO_IF_ID[63:0]=63'b0;
FROM_LS[511:480]= 32'b00011_00000_00100_01100_11100_10111_01;
FROM_LS[479:448]=32'b00_11000_00100_01111_11111_00011_10000;
end
always
begin
#10 CLK= ~ CLK;
//FROM_LS[511:448]= ~ FROM_LS[511:448];
$display("FROM_LS= %b", FROM_LS);
$display("TO_IF_ID= %b", TO_IF_ID);
end
endmodule
and here is the code for the design block:
module inst_line_buffer(input wire [511:0]from_LS,
input wire clk,
output reg [63:0]to_if_id);
parameter mem_size=16;
integer k;
reg [31:0] ilb[0:mem_size-1];
initial
begin
for (k = 0; k < mem_size ; k = k + 1)
begin
ilb[k] = 32'b00;
//$display ("ilb= %b",ilb[k]);
end
end
always #(posedge clk)
begin
ilb[0]= from_LS[511:480];
ilb[1]= from_LS[479:448];
ilb[2]= from_LS[447:416];
ilb[3]= from_LS[415:384];
ilb[4]= from_LS[383:352];
ilb[5]= from_LS[351:320];
ilb[6]= from_LS[319:288];
ilb[7]= from_LS[287:256];
ilb[8]= from_LS[255:224];
ilb[9]= from_LS[223:192];
ilb[10]= from_LS[191:160];
ilb[11]= from_LS[159:128];
ilb[12]= from_LS[127:96];
ilb[13]= from_LS[95:64];
ilb[14]= from_LS[63:32];
ilb[15]= from_LS[31:00];
to_if_id [63:32]= ilb[0];
to_if_id [31:0]= ilb[1];
$display("ilb= %b", ilb[1]);
end
endmodule
I'm expecting that the value of TO_IF_ID should be 0001100000001000110011100101110100110000010001111111110001110000, but I'm getting all zeros.
When you run a simulation on your testbench module, TO_IF_ID is always 0 because you only assigned a value to it once at time 0 in your initial block. If you want the value to change, it needs to be driven somehow.
As Andy pointed out in a comment, you probably meant to instantiate the inst_line_buffer module in your testbench. Verilog will not do this magically for you. But then, you should declare TO_IF_ID as a wire instead of a reg and remove it from the initial block.
module testbench;
reg [511:0]FROM_LS;
reg CLK;
wire [63:0]TO_IF_ID;
inst_line_buffer inst_line_buffer (
.from_LS (FROM_LS),
.clk (CLK),
.to_if_id (TO_IF_ID)
);
initial begin
CLK= 0;
FROM_LS[511:480]= 32'b00011_00000_00100_01100_11100_10111_01;
FROM_LS[479:448]=32'b00_11000_00100_01111_11111_00011_10000;
#500 $finish;
end
always
begin
#10 CLK= ~ CLK;
//FROM_LS[511:448]= ~ FROM_LS[511:448];
$display("FROM_LS= %b", FROM_LS);
$display("TO_IF_ID= %b", TO_IF_ID);
end
endmodule