generating random the same numbers in verilog issue - verilog

I'm trying to generate the random numbers in verilog in verilog.
But the Problem is when I re-run the simulation, that random value is fixed.
so previous simulation value and current simulation random value are the same.
reg [20:0] temp;
integer seed;
reg [31:0] rand;
initial fork
seed = $random;
for (i=0; i<10; i=i+1)begin
temp = $random(seed) %10 ;
end
wait(verif_fcnt == 3) begin
temp = $random(seed) %10 ;
task1(temp[0],temp[7:0]);
end
wait(verif_fcnt == 3) begin
temp = $random(seed) %10;
task2(temp[0],temp[7:0]);
end
wait(verif_fcnt == 3) begin
temp = $random(seed) %10;
task3(temp[0],temp[7:0]);
end
join

In order to reproduce a bug, you want to 'control' the randomness. So that is something you want most of the time.
The $random system call is constrained by seed. When a seed is give the random calls will give the same sequence.
I would advise you to keep the seed parameter and generate it by a $random call (without seed). Just be sure to print the seed variable used in case you stumble upon a bug.
Instead of:
seed = 0;
Use:
seed = $random;
$display("Seed used: %d",seed);
EDIT
Seed value can also be set in the simulation command-line.
In NCsim for example, it is the -seed integer option that sets it.
In this case, you can add in your simulation script:
#!/bin/bash
export SEED=$RANDOM
echo "Seed used: $SEED"
ncsim ...various command line options... -seed $SEED
EDIT 2
Verilog actually behaves (by default) like constant a seed is given so you can reproduce bugs (see here).
To manually pass a seed in Verilog source, you will have to use $srandom(seed) to initialize the seed of the next random calls. Then you should use $urandom instead of $random (see here)
To generate the inital seed, I would try to use $urandom before setting the seed.
integer seed;
initial begin
seed = $urandom();
$srandom(seed);
end
//**
... tests with $urandom() calls
**//
IMHO, It will finally be simpler to use the command line option.

Related

Initialize parameter from array

I have a parameterised module whose SEED value has to change depending on the WIDTH parameter, where the seed values have to be hard-coded.
module Module;
parameter WIDTH = 8;
integer seeds [31:0] = {'hC, 'h1E, 'h39, 'h7E, /* ... */};
localparam SEED = seeds[WIDTH];
endmodule
This doesn't work, It's clear I'm trying to use the unpacked array in the wrong context.
Unable to bind parameter seeds[WIDTH] in module Module
How else can I implement this?
After adjusting the post to compile with the truncated 4-element array, Questa shows:
** Error: testbench.sv(): Parameter value must be constant.
Parameters and localparams can't accept variable values.
Integer is a variable type, it can change at run time.
Parameters must be known an compile time.
This compiles without warnings:
module Module;
parameter WIDTH = 1;
parameter integer seeds[4] = {4'hC, 8'h1E, 8'h39, 8'h7E};
localparam SEED = seeds[WIDTH];
initial
$display("SEED = %0h",SEED);
endmodule
Questa Produces:
# vsim -voptargs=+acc=npr
# run -all
# SEED = 1e
This has an array of 4 hex values, and uses index 1 (WIDTH==1) as an argument to seeds.

Proper way to use a bus in a for loop in SystemVerilog?

I'm trying to make a module in SystemVerilog that can find the dot product between two vectors with up to 8 8-bit values. I'm trying to make it flexible for vectors of different length, so I have an input called EN that's 3 bits and determines the number of multiplications to perform.
So, if EN == 3'b101, the first five values of each vector will be multiplied and added together, then output as a 32-bit value. Right now, I'm trying to do that like:
int acc = 0;
always_comb
begin
for(int i = 0; i < EN; i++) begin
acc += A[i] * B[i];
end
end
assign OUT = acc;
Where A and B are the two input vectors. However, SystemVerilog is telling me there's an illegal comparison being performed between i and EN.
So my questions are:
1) Is this the proper way to have a variable vector "length" in SystemVerilog?
2) If so, what's the proper way to iterate n times where n is the value on a bus?
Thank you!
I have to guess here, but I'm assuming it's a synthesizer complaining about that code. The synthesizer I use accepts your code with minor modifications, but maybe not all do since the loop can't be unrolled statically (notice I have input logic [2:0] EN, maybe input int EN does not work due to having too big a max number of cycles). Your loop per se (question #2) is fine.
int acc;
always_comb
begin
// If acc is not reset always_comb tries to update on its old value and puts
// it in sensitivity list, halting simulation... also no initialization to variable
// used in always_comb is allowed.
acc = 0;
...
This is a somewhat decent reason to complain about your otherwise perfectly good code, and the tool does not make the assumption that it is "reasonable" to generate all possible loops in this specific case (if EN was an unsigned integer your chip would be stupidly huge after all): you can force the tool to infer all possibilities with something that looks like the following:
module test (
input int A[8],
input int B[8],
input logic [2:0] EN,
output int OUT
);
int acc[8]; // 8 accumulators
always_comb begin
acc[0] = A[0] * B[0]; // acc[-1] does not exist, different formula!
for (int i = 1; i < 8; i++) begin
// Each partial sum builds on previous one.
acc[i] = acc[i-1] + (A[i] * B[i]);
end
end
assign OUT = acc[EN]; // EN used as selector for a multiplexer on partial sums
endmodule: test
The above module is an explicit description of the "parallel loop" my synthesizer infers.
Regarding your question #1, the answer is "it depends". In hardware there is no variable length, so unless you fix the number of iterations as a parameter as opposed to an input you either have a maximum size and ignore some values or you iterate over multiple cycles using pointers to some memory. If you want to have a variable vector length in a test (not going to silicon) then you can declare a "dynamic array" that you can resize at will (IEEE 1800-2017, 7.5: Dynamic arrays):
int dyn_vec[];
As a final side note, int bad integer good for everything that is not testbench in order to catch X values and avoid RTL-synthesis mismatch.

One-way switch in verilog

I need to hold a value so that once it switches to one, it won't switch back to zero.
I am trying to make a Hangman game for an FPGA board. To do so, I have a constant onesLetter which is the correct letter to be displayed. The user has to guess letters. Once the onesLetter has been guessed correctly, I want to display it and keep displaying it during other guesses (not reverting back to the default display).
Here is what I have come up with:
// onesLetter is a constant we are checking against
// tempBooleanOnes represents if letter is currently being guessed
// tempSeg is input to check against onesLetter
// boolean is an input bit
wire tempBooleanOnes = (boolean && (onesLetter == tempSeg));
// Represent whether letter has been guessed or not
wire booleanOnes;
// Whether letter has been guessed or is being guessed
assign booleanOnes = (booleanOnes) || (tempBooleanOnes);
That is the expression I need to implement. However, I get an error saying I can't use booleanOnes for both the assigned wire and the expression. I've tried using a module register (output, input, clock, enable, reset) that I've implemented, with the enable being ~booleanOnes (do not overwrite when already 1, or already guessed) and the output being booleanOnes, but that also raises an error.
This is the code for the register module I have tried in place of the assign statement.
register regOnes(booleanOnes, tempBooleanOnes, clk, ~booleanOnes, 1'b0);
You shouldn't do this:
assign booleanOnes = (booleanOnes) || (tempBooleanOnes);
Since you're assigning to and from the same wire.
This code will set booleanOnes to 1 and will never be reset.
reg booleanOnes = 0;
always #* begin
if(boolean && (onesLetter == tempSeg)) begin
booleanOnes = 1;
end
end

module selection in verilog

I have a group of modules, say module_1, module_2, ... module_N. They perform similar yet different logic operations (out = logic_n). However, since the N is very large (thousands), it is unfeasible to use them in a higher level module by manually instantiate them. I was trying to write a python code for this. I was also wondering is that possible to use parameterized module for this purpose? What I mean is something like.
module module_generic(in, out)
parameter module_number;
case (module_number)
0 : out = logic_1;
1 : out = logic_2;
...
N : out = logic_N;
endcase
endmodule
By doing this, I can use generate statement to easily generate the code in the higher level module. Has anyone try this method before? Can it behave like the way I want? After synthesis, is it equivalent to the brute-force solution?
Something like this?
module module_generic#(
parameter module_number = 0
)(
input logic in,
output logic out);
generate
case (module_number)
0 : assign out = in;
//1 : assign out = logic_2;
//...
//N : assign out = logic_N;
endcase
endgenerate
endmodule
This module can now be instantiated in your code with different inputs for parameter module_number. Unless a lot of the same code is used for each logic_X I don't really understand why you would want to do this. Nevertheless, as far as I could understand from your question, this should do it.
Edit in reply to comment:
Generate is used to generate repeated and conditional parts of the code based on some parameter (e.g. in a parameterized module). For example:
generate
if(INPUT_PARAMETER)
assign out = in;
else //Tie low
assign out = 0;
endgenerate
or
genvar N;
generate
for(N = 0; N < INPUT_PARAMETER; N++) begin :la_someModule
someModule(.out(out[N]), .in(in[N]));
end
endgenerate
or both. (Take note of the label la_someModule. It is very smart to include this when using generate for , it simplifies debugging.)
Specifically answering the question you have asked here is hard. You have not provided enough information for me to understand what you need.

Verilog net to reg assignment

I have an input port from_LS(511:0). This is declared as wire in my module. I am assigning this to a set of 32 registers ilb(0:31), each of which are 1 nits long. I was trying to use the for loop to do this.
integer i;
genvar j;
initial
begin
count1 = 0;
count2=0;
flush_ctrl=0;
buffer_bit=0;
a=(hmic_ctrl[1]) + (hmic_ctrl[2]*2) + (hmic_ctrl[3]*4);
//assigning data from LS to ilb
for (i=0;i<=31;i=i+1)
ilb[i]=from_LS[511-(16*i) : 511-(16*(i-1))];
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
ilb[3]= from_LS[463:448];
ilb[4]= from_LS[447:432];
ilb[5]= from_LS[431:416];
ilb[6]= from_LS[415:400];
ilb[7]= from_LS[399:384];
ilb[8]= from_LS[383:368];
ilb[9]= from_LS[367:352];
ilb[10]= from_LS[351:336];
ilb[11]= from_LS[335:320];
ilb[12]= from_LS[319:304];
ilb[13]= from_LS[303:288];
ilb[14]= from_LS[287:272];
ilb[15]= from_LS[271:256];
ilb[16]= from_LS[255:240];
ilb[17]= from_LS[239:224];
ilb[18]= from_LS[223:208];
ilb[19]= from_LS[207:192];
ilb[20]= from_LS[191:176];
ilb[21]= from_LS[175:160];
ilb[22]= from_LS[159:144];
ilb[23]= from_LS[143:128];
ilb[24]= from_LS[127:112];
ilb[25]= from_LS[111:96];
ilb[26]= from_LS[95:80];
ilb[27]= from_LS[79:64];
ilb[28]= from_LS[63:48];
ilb[29]= from_LS[47:32];
ilb[30]= from_LS[31:16];
ilb[31]= from_LS[15:0];
pctr(
.clk(clk),
.reset(0),
.offset(branch_ctrl[13:1]),
.mux_select(branch_ctrl[0]),
.pc1(pc)
);
end
I was getting the error that I should not use a variable index. The error is :
# ** Error: C:/Modeltech_pe_edu_10.0/examples/COMP ARC/inst_line_buf.v(55): Range must be bounded by constant expressions.
So i wrote down the following:
ilb[0]= from_LS[511:496];
ilb[1]= from_LS[495:480];
ilb[2]= from_LS[479:464];
....
ilb[31]= from_LS[15:0];
But i guess there must be a better way to do this. Could anyone tell me how?
The orginal verilog doesnt allow this kind of expression as it wanted to assure that the width is always right (it is, but in earlier times compilers werent as good :-).
Verilog 2001 offers some solution with +: you can specify the width
e.g. from_LS[ 511-(16*i) +:16 ] in your loop.
EDIT: Another solution would be to put another loop inside, which copies 16 bits bit by bit.
You should include more code (at least up to the always block containing that loop for the sensitivity list) and the exact error you're getting.
Does it work if you change integer i to genvar i and wrap the for in generate and endgenerate?

Resources