verilog generate instances from another module in always #(posedge clk) - verilog

module save_random (clk,in,out);
parameter size=10;
parameter k=10;
input clk;
input [k-1:0] in;
output [k-1:0]out;
wire [size:0] cout;
genvar i;
generate
for(i=0;i<size;i=i+1)
begin: level1
always#(posedge clk) begin
random ins(clk,in[i],cout[i+1]);//generte 10 instances from module random to save it //in registers
end
end
endgenerate
assign cout[0]=in[0];
assign out=cout[k];
endmodule
I am just starting to learn verilog,
i have a task to write synthesis code that generate 10 random values and save each value in register or Dflipflop or sth like this.
The first(save_random) module that generate 10 instances from module random(the 2nd one) and connected ..but still have error when I am using clk input with generate i..
module random(clk,d,cout);
parameter size=8;
input [size-1:0] d;
input clk;
output [size-1:0]cout;
reg [size-1:0]cout;
integer i;
always#(posedge clk)
begin
cout<=d;
end
endmodule

You cannot instantiate modules inside an always block. As you have a module random which is a register of size size, you only need to instantiate that module inside your generate if you need more than one:
genvar i;
generate begin
for(i=0;i<size;i=i+1) begin: level1
random ins(clk,in[i],cout[i+1]);
end
end
However, note that in[i] and cout[i+1] are not an 8-bit values. So if you want to use the full 8-bit register, you need to declare them to be 10 (or 11 for cout) 8-bit vectors:
input [7:0] in [9:0];
wire [7:0] cout [10:0];
This tutorial might give you a better idea how generate blocks work: https://www.youtube.com/watch?v=5CKfP4n9ge0

Related

Writing random data to a RAM in a testbench

I am working with RAM in Verilog, and I need to implement a test bench where I will confirm the correct operation of the three memory processes (write data, read data and read commands). I have written a testbench where it seems to be writing and reading some integer numbers, but is there any way to fill the memory with words or strings to be more clear randomly?
This is my testbench:
module ramtest();
parameter WORD_SIZE=8;
parameter ADDR_WIDTH=8;
parameter RAM_SIZE=1<<ADDR_WIDTH;
reg we;
reg re;
reg [ADDR_WIDTH-1:0] addr;
reg [ADDR_WIDTH-1:0] instraddr;
reg [WORD_SIZE-1:0] datawr;
reg Clk;
reg [WORD_SIZE-1:0] mem[RAM_SIZE-1:0];
wire [WORD_SIZE-1:0] datard;
wire [WORD_SIZE-1:0] instrrd;
MCPU_RAMController raminst (.we(we),.datawr(datawr),.re(re),.addr(addr),.datard(datard),.instraddr(instraddr),.instrrd(instrrd));
integer i;
initial begin
we=0;
datawr=0;
instraddr=0;
addr=1;
#20;
for(i=0;i<RAM_SIZE;i=i+1) begin
datawr=i;
addr=i-1;
#10;
end
we=0;
addr=1;
instraddr=0;
for(i=0;i<RAM_SIZE;i=i+1) begin
addr=i-1;
#10;
end
end
endmodule
And here is the RAM controller code where I need to test:
module MCPU_RAMController(we, datawr, re, addr, datard, instraddr, instrrd);
parameter WORD_SIZE=8;
parameter ADDR_WIDTH=8;
parameter RAM_SIZE=1<<ADDR_WIDTH;
input we, re;
input [WORD_SIZE-1:0] datawr;
input [ADDR_WIDTH-1:0] addr;
input [ADDR_WIDTH-1:0] instraddr;
output [WORD_SIZE-1:0] datard;
output [WORD_SIZE-1:0] instrrd;
reg [WORD_SIZE-1:0] mem[RAM_SIZE-1:0];
reg [WORD_SIZE-1:0] datard;
reg [WORD_SIZE-1:0] instrrd;
always # (addr or we or re or datawr)
begin
if(we)begin
mem[addr]=datawr;
end
if(re) begin
datard=mem[addr];
end
end
always # (instraddr)
begin
instrrd=mem[instraddr];
end
endmodule
Currently, you are filling the memory with incrementing values (0, 1, 2, etc.) at incrementing addresses. One way to fill the memory with random data values is to use the $random system function.
In the testbench, change:
datawr=i;
to:
datawr=$random;
See also IEEE Std 1800-2017, section 18.13 Random number system functions and methods for more modern random functions ($urandom, etc.).

Quartus does not allow using a Generate block in Verilog

Pretty simple problem. Given the following code:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
generate
genvar k;
for(k=0; k<2; k=k+1) begin: m
always #(posedge clk) begin
if(wren[k])
ram[addr[k]] <= dIn[k];
dOut[k] <= ram[addr[k]];
end
end
endgenerate
endmodule
quarus 13.0sp1 gives this error (and its 20 other ill-begotten fraternally equivalent siblings):
Error (10028): Can't resolve multiple constant drivers for net "ram[63][14]" at main.v(42)
But if I manually un-roll the generate loop:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
always #(posedge clk) begin
if(wren[0])
ram[addr[0]] <= dIn[0];
dOut[0] <= ram[addr[0]];
end
always #(posedge clk) begin
if(wren[1])
ram[addr[1]] <= dIn[1];
dOut[1] <= ram[addr[1]];
end
endmodule
It all becomes okay with the analysis & synthesis step.
What's the cure to get the generate loop running?
I think the correct way is in the lines of what it's explained in this question: Using a generate with for loop in verilog
Which would be transferred to your code as this:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
integer k;
always #(posedge clk) begin
for(k=0; k<2; k=k+1) begin:
if(wren[k])
ram[addr[k]] <= dIn[k];
dOut[k] <= ram[addr[k]];
end
end
endmodule
Keeping all accesses to your dual port RAM in one always block is convenient so the synthesizer can safely detect that you are efefctively using a dual port RAM at register ram.
Both the generate loop and unrolled versions should not have passed synthesis. In both cases the same address in ram can be assigned by both always blocks. Worse, if both bits of wren are high with both addresses being the same and data being different, then the result is indeterminable. The Verilog LRM states last assignment on a register wins and always blocks with the same trigger could be evaluated in any order.
Synthesis requires assignments to registers to be deterministic. Two (or more) always blocks having write access to the same bit is illegal because nondeterministic. If the unrolled is synthesizing correctly, then that means there are constants on wren and addr outside of the shown module that make it logically impossible for write conflict; for some reason the generate loop version is not getting the same optimization. Example of constraints that would allow optimization to prevent multi-always block write access:
One wren is hard coded to 0. Therefore only one block has exclusive access
Address have non overlapping sets of possible values. Ex addr[0] can only be even while addr[1] can only be odd, or addr[0] < 2**(ADDR_WIDTH/2) and addr[1] >= 2**(ADDR_WIDTH/2).
Synthesis is okay with dOut being assigned by two always blocks because each block has exclusive write access to its target bits (non overlapping sets of possible address values).
The single always block in mcleod_ideafix answer is the preferred solution. If both bits of wren are high with both addresses being the same, then wren[1] will always win. If wren[0] should have priority, then make the for-loop a count down.

Confused with ripple carry adder output

I am working on a ripple carry adder using structural verilog, which is supposed to take in two random inputs and calculate accordingly.
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Could someone kindly explain where I'm going wrong? Below is my code:
module full_adder(x,y,z,v,cout);
parameter delay = 1;
input x,y,z; //input a, b and c
output v,cout; //sum and carry out
xor #delay x1(w1,x,y);
xor #delay x2(v,w1,z);
and #delay a1(w2,z,y);
and #delay a2(w3,z,x);
and #delay a3(w4,x,y);
or #delay o1(cout, w2,w3,w4);
endmodule
module four_bit_adder(a,b,s,cout,cin);//four_bit_adder
input [15:0] a,b; //input a, b
input cin; //carry in
output [15:0] s; //output s
output cout; //carry out
wire [15:0] c;
full_adder fa1(a[0],b[0],cin,s[0],c0);
full_adder fa2(a[1],b[1],c0,s[1],c1);
.
.
.
full_adder fa16(a[15],b[15],c14,s[15],cout);
endmodule
module testAdder(a,b,s,cout,cin);
input [15:0] s;
input cout;
output [15:0] a,b;
output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
initial begin
for(i=0; i<5000; i=i+1) begin
a = $random(seed1);
b = $random(seed2);
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
Here are two lines from the output that I get:
a=38893, b=58591, cin=x, s= z, cout=z
a=55136, b=58098, cin=x, s= z, cout=z
This is a combinational circuit, so the output changes instantaneously as the input changes. But, here you are apply all the inputs at same timestamp which should not be done since the full_adder module provides 1-timestamp delay. This may not cause problems in this module, but may cause issues while modelling sequential logic. Add a minimum of #10 delay between inputs.
Also, $monitor executes on each change in the signal list, so no need to use it in for loop. Just initialize $monitor in initial condition.
cin is also not driven from the testbench. Default value of reg is 'x and that of wire is 'z. Here, cin is reg, so the default value is displayed, that is 'x
One more thing, you must instantiate the design in your testbench. And connect respective ports. The outputs from testbench act as inputs to your design and vice-versa. This is just like you instantiate full_adder module in four_bit_adder module in design.
Consider testadder as top level module and instantiate design in it. No need of declaring ports as input and output in this module. Declare the design input ports as reg or wire(example: reg [15:0] a when a is design input port) and output ports as wire (example: wire [15:0] sum when sum is design input port).
Referring to your question:
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Instead of using $random, use $urandom_range() to generate random numbers in some range. Using SystemVerilog constraints constructs can also help. Refer this link.
Using $urandom_range shall eliminate use of seed1 and seed2, it shall generate random values with some random machine seed.
Following is the module testadder with some of the changes required:
module testAdder();
wire [15:0] s;
wire cout;
// output [15:0] a,b;
// output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
// Instantiate design here
four_bit_adder fa(a,b,s,cout,cin);
initial begin
// Monitor here, only single time
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
for(i=0; i<5000; i=i+1) begin
// Drive inputs with some delays.
#10;
// URANDOM_RANGE for input generation in a range
a = $urandom_range(0,15);
b = $urandom_range(0,15);
// a = $random(seed1);
// b = $random(seed2);
// Drive cin randomly.
cin = $random;
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
For more information, have a look at sample testbench at this link.

Register variable in port declaration in verilog

I want to make a module in Verilog which must get a 32 bit wide register variable in port. This variable will be used to count the clock cycle. Then this module will be instantiated in another module. For example: when I fix the value of counter this module must start count from that value.
When I simulate this code I get an error:
Non-net port count cannot be of mode input
module case_1( input clk , input [31:0] counter);
reg [31:0] counter;
always # (posedge clk)
begin
counter <=counter +1
end
endmodule
module counter (input clk , input [31:0] counter )
reg [31:0] counter;
case_1 h1 ( .clk(clk) , .counter(counter) )
endmodule
If a module is an input then you can not drive a value on to it. Driving a value on to an input does not make sense. It needs to be an output.
It think there might be some confusion over the reg and wire types in verilog. These types do not cross module interfaces. a lower (sub) module drives its output as a reg type. the next level up a wire is connected to the port.
From your example a clock received by counter which uses sub module case_1 to implement the counter. Counter value is then driven (first as a reg) then at the top level as a wire.
module case_1(
input clk ,
output reg [31:0] counter
);
initial begin
counter = 'b0;
end
always # (posedge clk) begin
counter <=counter +1;
end
endmodule
module counter (input clk , output wire [31:0] counter );
case_1 h1 ( .clk(clk) , . counter(counter) );
endmodule
Example on EDA Playground.

Parameterized number of cycle delays in verilog?

I have to delay a few control signals in a pipeline I've designed by the number of stages in the pipeline. This is obviously very straight forward -- just put N flip-flops in between the the input signal and output signal. I'm wondering if there's a way to parameterize N. If I ever change the number of stages in the pipeline I have to go back and add/remove flip-flops, which is sort of annoying. I thought about just writing a script to read a define somewhere and generate the module, but that seems like overkill. Is a genvar loop the right way to go here?
You could use a parameterized shift register to do this. Something like:
module shift
(
input clk,
input data_in,
output data_out
);
parameter DEPTH = 3;
reg [DEPTH-1:0] holding_register;
always # (posedge clk) begin
holding_register <= {holding_register[DEPTH-2:0], data_in};
end
assign data_out = holding_register[DEPTH-1];
endmodule
Another alternative would be to use a generate statement to create essentially the same effect.
Here is how to created the parameterized shift register using a generate block and a DFF module. It even works with DEPTH=0 and DEPTH=1.
module shift
(
input clk,
input reset,
input data_in,
output data_out
);
parameter DEPTH = 3;
wire [DEPTH:0] connect_wire;
assign data_out = connect_wire[DEPTH];
assign connect_wire[0] = data_in;
genvar i;
generate
for (i=1; i <= DEPTH; i=i+1) begin
dff DFF(clk, reset,
connect_wire[i-1], connect_wire[i]);
end
endgenerate
endmodule
Complete working code with a test on EDA Playground: http://www.edaplayground.com/s/4/50

Resources