I am writing a ripple counter using D-Flip Flops. However the following code is giving me Illegal reference error inside initial block for q2,q3,q4variables. Why is that?
module RCounter;
reg d,d2,d3,d4,clk;
wire q,q2,q3,q4;
DFlipFlop a(d,q,clk);
DFlipFlop a1(d2,q2,q);
DFlipFlop a2(d3,q3,q2);
DFlipFlop a3(d4,q4,q3);
initial
begin
clk =1;
d=0;d2=0;d3=0;d4=0;q2=0;q3=0;q4=0;
#2 d=1;d2=~q2; d3=~q3; d4=~q4;
#2 d=0;d2=~q2; d3=~q3; d4=~q4;
#2 d=1;d2=~q2; d3=~q3; d4=~q4;
#2 d=0;d2=~q2; d3=~q3; d4=~q4;
#2 d=1;d2=~q2; d3=~q3; d4=~q4;
#2 d=0;d2=~q2; d3=~q3; d4=~q4;
#2 d=1;d2=~q2; d3=~q3; d4=~q4;
end
always
begin
#2 assign clk = ~ clk;
end
endmodule
D FlipFlop module:
module DFlipFlop(d,q,clk);
input d,clk;
output q;
assign q = clk?( (d==1)? 1:0) : q;
endmodule
How can I solve this problem?
Regards
As Vlad Lazarenko has pointed out you can not assign values to wires inside initial or always# blocks.
The fix for this is to simply to change the type from wire to reg.
Or declare everything (except tristate buses) as logic if you are using SystemVerilog.
The definition of reg or wire only applies to that level of hierarchy. A reg can drive a port which is treated as wire inside that module.
Reg does not imply a flip-flop or register it is a simulator optimisation.
It is also worth noting that a flip-flop is normally instantiated via:
reg x;
always #(posedge clk or negedge rst_n) begin
if(~rst_n) begin
//reset condition
x <= 1'b0;
end
else begin
x <= next_value;
end
end
You are trying to assign initial values to wires, here:
q2=0;q3=0;q4=0;
That is illegal.
Related
I'm trying to make an SR flipflop on Icarus Verilog.
Flipflop module:
module srff(sr,clk,q,qb);
input [1:0]sr;
input clk;
output reg q,qb;
always#(posedge clk) begin
case(sr)
2'b00: q=q;
2'b01: q=0;
2'b10: q=1;
2'b11: q=1'bz;
endcase
end
assign qb=~q;
endmodule
Testbench:
module sr_ff_test;
reg [1:0]sr;
reg clk;
wire q,qbar;
srff sr_ff_test(sr,clk,q,qbar);
initial begin $dumpfile("dump1.vcd");
$dumpvars(0,sr_ff_test);
end
initial begin
$monitor("S=%d, R=%d, CLK=%d, Q=%d, Qbar=%d",sr[0],sr[1],clk,q,qbar);
sr[0]=1'b0;
sr[1]=1'b1;
clk=1;
#100
sr[0]=1'b0;
sr[1]=1'b1;
#100
sr[0]=1'b0;
sr[1]=1'b0;
#100
sr[0]=1'b1;
sr[1]=1'b1;
#100
sr[0]=1'b0;
sr[1]=1'b1;
#100
sr[0]=1'b0;
sr[1]=1'b1;
end
endmodule
The error is as given in the question (line 14 of testbench - the one with monitor...). What went wrong, and how do I fix this?
I'm new to Icarus Verilog, and I don't know if I have accidentally used commands that aren't usable.
The error is in the srff module. You declared qb as a reg, but then you try to drive it with a continuous assignment using the assign keyword.
The solution is to not declare it as a reg. Change:
output reg q,qb;
to:
output reg q;
output qb;
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
module rff_try_1(q,inp,clk);
input clk,inp;
output q;
reg q;
DFF dff0(q,inp,clk);
endmodule
module DFF(q,inp,clk);
input inp,clk;
output q;
reg q;
always # (posedge clk)begin
if(clk)begin
q=inp;
end
end
endmodule
here I'm using two modules but output is not coming
I'm trying to make two bit right shift register but 1st i have to make one single bit register but even this is not working
There are several mistakes in the code.
1) The line if(clk)begin and relevant end should be removed, posedge clk already describes trigger condition of the flip-flop.
2) A non-blocking assignment (<=) is required for the sequential logic.
The always block should be as follows:
always # (posedge clk) begin
q <= inp;
end
3) Some simulators don't complain, but signal q should be wire in module rff_try_1.
wire q;
Simulation
I simulated the code (after the modifications) on EDA Playground with the testbench below. Used Icarus Verilog 0.9.7 as simulator.
module tb();
reg clk = 1;
always clk = #5 ~clk;
reg inp;
wire q;
rff_try_1 dut(q, inp, clk);
initial begin
inp = 0;
#12;
inp = 1;
#27;
inp = 0;
#24;
inp = 1;
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
#200;
$finish;
end
endmodule
The signal q is as expected as seen on the waveform.
I want to infer a simple flip flop using verilog. Here is the code.
module tb_simpleRegister();
reg clk;
reg a;
wire b;
simpleRegister dut
(
.clk(clk),
.a(a),
.b(b),
.c(c)
);
initial begin
clk=1;
a=0;
#10
a=1;
#10
a=0;
end
always #5 clk = ~clk;
endmodule
module simpleRegister(
input clk,
input a,
output reg b,
output reg c
);
always #(posedge clk) begin
b <= a;
c <= b;
end
endmodule
And here is the result when I run it. The b output of dut does not behave like a flip flop. However output c does. Any comments on why is this happening?
I would rewrite the test bench as follows:
initial begin
#(posedge clk);
a<=0;
#(posedge clk);
a<=1;
#(posedge clk);
a<=0;
end
//Clock in separate process
initial begin
clk=1;
forever begin
#5 clk = ~clk;
end
end
The non-blocking assignment will ensure the value of a is changed just after the clock edge giving the testbench a full cycle setup.
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