How to randomize 1 of 100 variables - verilog

Let's say we have a class with a bunch of random variables (around 100 rand variables). Now, I want to randomize only one of the variables from that class and the rest of the variables should be the same. How do I do that?
class rand_var extends vmm_data;
rand bit abc;
rand bit [3:0] cde;
rand bit en;
...
endclass
Now from one of the task, I want to randomize abc only, not any other variables of rand_var.
task custom_task();
rand_var rand1;
rand1 = new config
if (config.randomize () with {
})
else $display("randomization failed");

The easiest way of randomizing a single variable is using the std::randomize instead of the randomize method of the class.
task custom_task();
rand_var config;
config = new();
if (std::randomize(config.abc) with {
/* constraints on config.abc */
})
else $display("randomization failed");
You can also use what's called in-line randomization control when calling the class randomize method as in
if (!config.randomize(abc)) $display("randomization failed");
But you have to be careful when doing it this way because all of the active class constraints in the config object must still be satisfied, even on variables not being randomized.

One way is to call randomize and pass only the variable you want to be random. Refer to IEEE Std 1800-2017, section 18.11 In-line random variable control. Here is a complete example:
class rand_var;
rand bit abc;
rand bit [3:0] cde;
rand bit en;
endclass
module tb;
task custom_task();
rand_var rand1;
rand1 = new();
if (!rand1.randomize(abc)) $display("randomization failed");
$display("%b %d %b", rand1.abc, rand1.cde, rand1.en);
endtask
initial repeat (10) custom_task();
endmodule
Output:
1 0 0
1 0 0
1 0 0
0 0 0
1 0 0
1 0 0
0 0 0
1 0 0
1 0 0
0 0 0
Only abc is random for each task call.
See also How to randomize only 1 variable in a class?

Related

Shifter output is always 0 when using concatenation and case

I have the following code:
module shifter(
input[7:0] in,
input[1:0] amt,
output logic[7:0] out
);
always_comb case(amt)
2'h0: out = in;
2'h1: out = {{in[6:0]}, 0};
2'h2: out = {{in[5:0]}, 0, 0};
2'h3: out = {{in[4:0]}, 0, 0, 0};
default: out = in;
endcase
endmodule
It describes a simple shifter which takes in the amount of shifts through the amt input. The problem is that no matter what the value of amt is (except 0), out is always 0 as seen on this waveform from a test:
Am I concatenating wrong? Examples I've seen online are similar to this, however.
Try constraining the size of the 0 to 1'b0 in 2'h1: out = {{in[6:0]}, 0};. What happens is that you are assigning a concatenation of in[6:0] and 32-bit (default width) 0, so only LSBs of the 0 goes to the out.
Also, default is redundant since you've described all the possible cases for amt.
The code you wrote is illegal according to the IEEE 1800-2017 LRM section 11.4.12 Concatenation operators:
Unsized constant numbers shall not be allowed in concatenations. This
is because the size of each operand in the concatenation is needed to
calculate the complete size of the concatenation
The tool you are using has a bug and did not catch this error, which is very difficult to find on your own.

VHDL - String indexing - RAM usage and total logic elements increase by over 100% each

I'm hoping someone with more VHDL experience can enlighten me! To summarise, I have an LCD entity and a Main entity which instantiates it. The LCD takes an 84-character wide string ("msg"), which seems to cause me huge problems as soon as I index it using a variable or signal. I have no idea what the reason for this is, however, since the string is displaying HEX values, and each clock cycle, I read a 16-bit value... I need to update 4 characters of the string for each nybble of this 16-bit value. This doesn't need to be done in a single clock cycle, since a new value is read after a large number of cycles... however, experimenting with incrementing a "t" variable, and only changing string values one "t" at a time makes no difference for whatever reason.
The error is: "Error (170048): Selected device has 26 RAM location(s) of type M4K" However, the current design needs more than 26 to successfully fit
Here is the compilation report with the problem:
Flow Status Flow Failed - Tue Aug 08 18:49:21 2017
Quartus II 64-Bit Version 13.0.1 Build 232 06/12/2013 SP 1 SJ Web Edition
Revision Name Revision1
Top-level Entity Name Main
Family Cyclone II
Device EP2C5T144C6
Timing Models Final
Total logic elements 6,626 / 4,608 ( 144 % )
Total combinational functions 6,190 / 4,608 ( 134 % )
Dedicated logic registers 1,632 / 4,608 ( 35 % )
Total registers 1632
Total pins 50 / 89 ( 56 % )
Total virtual pins 0
Total memory bits 124,032 / 119,808 ( 104 % )
Embedded Multiplier 9-bit elements 0 / 26 ( 0 % )
Total PLLs 1 / 2 ( 50 % )
The RAM summary table contains 57 rows, of "LCD:display|altsyncram:Mux####_rtl_0|altsyncram_####:auto_generated|ALTSYNCRAM"
Here is the LCD entity:
entity LCD is
generic(
delay_time : integer := 50000;
half_period : integer := 7
);
port(
clk : in std_logic;
SCE : out std_logic := '1';
DC : out std_logic := '1';
RES : out std_logic := '0';
SCLK : out std_logic := '1';
SDIN : out std_logic := '0';
op : in std_logic_vector(2 downto 0);
msg : in string(1 to 84);
jx : in integer range 0 to 255 := 0;
jy : in integer range 0 to 255 := 0;
cx : in integer range 0 to 255 := 0;
cy : in integer range 0 to 255 := 0
);
end entity;
The following code is what causes the problem, where a, b, c and d are variables which are incremented by 4 after each read:
msg(a) <= getHex(data(3 downto 0));
msg(b) <= getHex(data(7 downto 4));
msg(c) <= getHex(data(11 downto 8));
msg(d) <= getHex(data(15 downto 12));
Removing some of these lines causes the memory and logic element usages to both drop, but they still seem absurdly high, and I don't understand the cause.
Replacing a, b, c and d with integers, like 1, 2, 3 and 4 causes the problem to go away completely, with the logic elements at 22%, and RAM usage at 0%!
If anybody has any ideas at all, I'd be very grateful! I will post the full code below in case anybody needs it... but be warned, it's a bit messy, and I feel like the problem could be simple. Many thanks in advance!
Main.vhd
LCD.vhd
There are a few issues here.
The first is that HDL synthesis tools do an awful lot of optimization. What this basically means is if you don't properly connect up input and output parts to/from something it is likely (but not certain) to get eliminated by the optimizer.
The second is you have to be very careful with loops and functions. Basically loops will be unrolled and functions will be inlined, so a small ammount of code can generate an awful lot of logic.
The third is that under some cicumstances arrays will be translated to memory elements.
As pointed out in a comment this loop is the root cause of the large ammounts of memory usage.
for j in 0 to 83 loop
for i in 0 to 5 loop
pixels((j*6) + i) <= getByte(msg(j+1), i);
end loop;
end loop;
This has the potential to use a hell of a lot of memory resources. Each call to "getByte" requires a read port on (parts of) "ram" but blockrams only have two read ports. So "ram" gets duplicated to satisfy the need for more read ports. The inner loop is reading different parts of the same location so basically each iteration of the outer loop needs an independent read port on the ram. So that is about 40 copies of the ram. Reading the cyclone 2 datasheet each copy will require 2 m4k blocks
So why doesn't this happen when you use numbers instead of the variables a,b,c and d?
If the compiler can figure out something is a constant it can compute it at compile time. This would limit the number of calls to "pixels" that have to actually be translated to memory blocks rather that just having their result hardcoded. Still i'm surprised it's dropping to zero.
I notice your code doesn't actually have any inputs other than the clock and a "rx" input that doesn't actually seem to be being used for anything, so it is quite possible that the synthesizer may be figuring out a hell of a lot of stuff at build time. Often eliminating one bit of code can allow another bit to be eliminated until you have nothing left.

GBZ80 - ADC instructions fail test

I've been running Blarggs CPU tests through my Gameboy emulator, and the op r,r test shows that my ADC instruction is not working properly, but that ADD is. My understanding is that the only difference between the two is adding the existing carry flag to the second operand before addition. As such, my ADC code is the following:
void Emu::add8To8Carry(BYTE &a, BYTE b) //4 cycles - 1 byte
{
if((Flags >> FLAG_CARRY) & 1)
b++;
FLAGCLEAR_N;
halfCarryAdd8_8(a, b); //generates H flag based on addition
carryAdd8_8(a, b); //generates C flag appropriately
a+=b;
if(a == 0)
FLAGSET_Z;
else
FLAGCLEAR_Z;
}
I entered the following into a test ROM:
06 FE 3E 01 88
Which leaves A with the value 0 (Flags = B0) when the carry flag is set, and FF (Flags = 00) when it is not. This is how it should work, as far as my understanding goes. However, it still fails the test.
From my research, I believe that flags are affected in an identical manner to ADD. Literally the only change in my code from the working ADD instruction is the addition of the flag check/potential increment in the first two lines, which my test code seems to prove works.
Am I missing something? Perhaps there's a peculiarity with flag states between ADD/ADC? As a side note, SUB instructions also pass, but SBC fails in the same way.
Thanks
The problem is that b is an 8 bit value. If b is 0xff and carry is set then adding 1 to b will set it to 0 and won't generate carry if added with a >= 1. You get similar problems with the half carry flag if the lower nybble is 0xf.
This might be fixed if you call halfCarryAdd8_8(a, b + 1); and carryAdd8_8(a, b + 1); when carry is set. However, I suspect that those routines also take byte operands so you may have to make changes to them internally. Perhaps by adding the carry as a separate argument so that you can do tmp = a + b + carry; without overflow of b. But I can only speculate without the source to those functions.
On a somewhat related note, there's a fairly simple way to check for carry over all the bits:
int sum = a + b;
int no_carry_sum = a ^ b;
int carry_into = sum ^ no_carry_sum;
int half_carry = carry_into & 0x10;
int carry = carry_info & 0x100;
How does that work? Consider that bitwise "xor" gives the expected result of each bit if there is no carry going in to that bit: 0 ^ 0 == 0, 1 ^ 0 == 0 ^ 1 == 1 and 1 ^ 1 == 0. By xoring sum with no_carry_sum we get the bits where the sum differs from the bit-by-bit addition. sum is only different whenever there is a carry into a particular bit position. Thus both the half carry and carry bits can be obtained with almost no overhead.

Minimum value over entire simulation

In a continuous model, how do I save the minimum value of a variable during the simulation?
When a simulation has finished I want to display a variable T_min with a graphical annotation that shows me the lowest value of a temperature T during the simulation.
For example, if the simulated temperature T was a sine function, the desired result for the value of T_min would be:
In discrete code this would look something like this:
T_min := Modelica.Constants.inf "Start value";
if T < T_min then
T_min := T;
else
T_min := T_min;
end if;
... but I would like a continuous implementation to avoid sampling, high number of events etc.
I'm not sure if Renes solution is optimal. The solution generates many state events generated by the two if conditions. Embedded in the following model:
model globalMinimum2
Real T, T_min;
Boolean is_true;
initial equation
T_min = T;
equation
T =time/10*sin(time);
// if statement ensures that 'T_min' doesn't integrate downwards...
// ... whenever der(T) is negative;
if T < T_min then
der(T_min) = min(0, der(T));
is_true=true;
else
der(T_min) = 0;
is_true=false;
end if;
end globalMinimum2;
The simulation log is the following:
Integration started at T = 0 using integration method DASSL
(DAE multi-step solver (dassl/dasslrt of Petzold modified by Dynasim))
Integration terminated successfully at T = 50
WARNING: You have many state events. It might be due to chattering.
Enable logging of event in Simulation/Setup/Debug/Events during simulation
CPU-time for integration : 0.077 seconds
CPU-time for one GRID interval: 0.154 milli-seconds
Number of result points : 3801
Number of GRID points : 501
Number of (successful) steps : 2519
Number of F-evaluations : 4799
Number of H-evaluations : 18822
Number of Jacobian-evaluations: 2121
Number of (model) time events : 0
Number of (U) time events : 0
Number of state events : 1650
Number of step events : 0
Minimum integration stepsize : 1.44e-005
Maximum integration stepsize : 5.61
Maximum integration order : 3
Perhaps it is better to detect two events as given in the following example:
model unnamed_2
Real T;
Real hold;
Real T_min;
Boolean take_signal;
initial equation
hold=T;
equation
T = time/10*sin(time);
when (T < pre(hold)) then
take_signal = true;
hold = T;
elsewhen (der(T) >=0) then
take_signal = false;
hold = T;
end when;
if (take_signal) then
T_min = T;
else
T_min = hold;
end if;
end unnamed_2;
The simulation log shows that this solutions is more efficient:
Log-file of program ./dymosim
(generated: Tue May 24 14:13:38 2016)
dymosim started
... "dsin.txt" loading (dymosim input file)
... "unnamed_2.mat" creating (simulation result file)
Integration started at T = 0 using integration method DASSL
(DAE multi-step solver (dassl/dasslrt of Petzold modified by Dynasim))
Integration terminated successfully at T = 50
CPU-time for integration : 0.011 seconds
CPU-time for one GRID interval: 0.022 milli-seconds
Number of result points : 549
Number of GRID points : 501
Number of (successful) steps : 398
Number of F-evaluations : 771
Number of H-evaluations : 1238
Number of Jacobian-evaluations: 373
Number of (model) time events : 0
Number of (U) time events : 0
Number of state events : 32
Number of step events : 0
Minimum integration stepsize : 4.65e-006
Maximum integration stepsize : 3.14
Maximum integration order : 1
Calling terminal section
... "dsfinal.txt" creating (final states)
It seems I was able to finde an answer to my own question simply by looking at the figure above
The code is quite simple:
model globalMinimum
Modelica.SIunits.Temperature T, T_min;
initial equation
T_min = T;
equation
// if statement ensures that 'T_min' doesn't integrate downwards...
// ... whenever der(T) is negative;
der(T_min) = if T < T_min then min(0, der(T)) else 0;
end globalMinimum;

LTL model checking using Spin and Promela syntax

I'm trying to reproduce ALGOL 60 code written by Dijkstra in the paper titled "Cooperating sequential processes", the code is the first attempt to solve the mutex problem, here is the syntax:
begin integer turn; turn:= 1;
parbegin
process 1: begin Ll: if turn = 2 then goto Ll;
critical section 1;
turn:= 2;
remainder of cycle 1; goto L1
end;
process 2: begin L2: if turn = 1 then goto L2;
critical section 2;
turn:= 1;
remainder of cycle 2; goto L2
end
parend
end
So I tried to reproduce the above code in Promela and here is my code:
#define true 1
#define Aturn true
#define Bturn false
bool turn, status;
active proctype A()
{
L1: (turn == 1);
status = Aturn;
goto L1;
/* critical section */
turn = 1;
}
active proctype B()
{
L2: (turn == 2);
status = Bturn;
goto L2;
/* critical section */
turn = 2;
}
never{ /* ![]p */
if
:: (!status) -> skip
fi;
}
init
{ turn = 1;
run A(); run B();
}
What I'm trying to do is, verify that the fairness property will never hold because the label L1 is running infinitely.
The issue here is that my never claim block is not producing any error, the output I get simply says that my statement was never reached..
here is the actual output from iSpin
spin -a dekker.pml
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DSAFETY -DNOCLAIM -w -o pan pan.c
./pan -m10000
Pid: 46025
(Spin Version 6.2.3 -- 24 October 2012)
+ Partial Order Reduction
Full statespace search for:
never claim - (not selected)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 44 byte, depth reached 8, errors: 0
11 states, stored
9 states, matched
20 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.001 equivalent memory usage for states (stored*(State-vector + overhead))
0.291 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
unreached in proctype A
dekker.pml:13, state 4, "turn = 1"
dekker.pml:15, state 5, "-end-"
(2 of 5 states)
unreached in proctype B
dekker.pml:20, state 2, "status = 0"
dekker.pml:23, state 4, "turn = 2"
dekker.pml:24, state 5, "-end-"
(3 of 5 states)
unreached in claim never_0
dekker.pml:30, state 5, "-end-"
(1 of 5 states)
unreached in init
(0 of 4 states)
pan: elapsed time 0 seconds
No errors found -- did you verify all claims?
I've read all the documentation of spin on the never{..} block but couldn't find my answer (here is the link), also I've tried using ltl{..} blocks as well (link) but that just gave me syntax error, even though its explicitly mentioned in the documentation that it can be outside the init and proctypes, can someone help me correct this code please?
Thank you
You've redefined 'true' which can't possibly be good. I axed that redefinition and the never claim fails. But, the failure is immaterial to your goal - that initial state of 'status' is 'false' and thus the never claim exits, which is a failure.
Also, it is slightly bad form to assign 1 or 0 to a bool; assign true or false instead - or use bit. Why not follow the Dijkstra code more closely - use an 'int' or 'byte'. It is not as if performance will be an issue in this problem.
You don't need 'active' if you are going to call 'run' - just one or the other.
My translation of 'process 1' would be:
proctype A ()
{
L1: turn !=2 ->
/* critical section */
status = Aturn;
turn = 2
/* remainder of cycle 1 */
goto L1;
}
but I could be wrong on that.

Resources