I have [8:0] digital data inputs. I want to pre-define these values and store them with a unique address so I can access them later in my logic by just calling their address value.
Not entirely sure, I was doing something like this (Also, this is for Verilog RTL (Syntheisizable):
reg array[8:0];
array[8] = 9'b000000000;
array[7] = 9'b000000001;
array[6] = 9'b000000010;
array[5] = 9'b000000011;
array[4] = 9'b000000100;
array[3] = 9'b000000101;
array[2] = 9'b000000111;
array[1] = 9'b000001000;
array[0] = 9'b000000000;
I'm not sure, this is just something that was on top of my head.
If youre looking to create a LUT (which is basically want you are suggesting), you are on the right track:
reg [8:0] lut [8:0]; // Its an array of 9 elements (0 through 8 after the variable name), each of which is 9 bits wide (before the variable name)
assign lut[8] = 9'b000000000; // If there is a pattern to the array, use generate statement and loops to initialize it, Im just doing it one-by-one here
assign lut[7] = 9'b000000001;
assign lut[6] = 9'b000000010;
assign lut[5] = 9'b000000011;
assign lut[4] = 9'b000000100;
assign lut[3] = 9'b000000101;
assign lut[2] = 9'b000000111;
assign lut[1] = 9'b000001000;
assign lut[0] = 9'b000000000;
Related
I'm new to NuSMV. I'm trying to define a module, where each state has a duration variable than can range from 0 to the specified bound.
MODULE state(inc, bound)
VAR
duration : 0..bound;
ASSIGN
init(duration) := 0;
next(duration) := inc ? (duration + 1) mod (bound+1) : duration ;
DEFINE limit := duration = bound;
However, this yields the syntax error: A variable is expected in left-hand-side of assignment: init(duration) := 0. I'm able to fix this by declaring duration to duration : 0..1+bound.
In my main module, I wish to calculate the total_duration (or actually calculate all possible combinations of state's duration and make sure that no combination exceeds e.i. 3 as in the SPEC) of running my model and make sure that variable does not succeed a specific limit.
Here's my main module:
MODULE main
VAR
s0 : state(TRUE, 0);
s1 : state(s0.limit, 0);
s2 : state(s1.limit, 3);
state : {s0, s1, s2};
DEFINE
max_duration := s0.bound + s1.bound + s2.bound;
VAR
total_duration : 0..max_duration;
ASSIGN
init(state) := s0;
next(state) :=
case
state = s0 : s1;
state = s1 : s2;
state = s2 : s2;
esac;
total_duration := s0.duration + s1.duration + s2.duration;
SPEC
AG (state = s2 -> AF total_duration <= 3);
My problem is: When I run the model, NuSMV keeps adding to the total_duration variable and thus fails with the message "line 39: cannot assign value 5 to variable total_duration". This is due to the declaration of duration : 0..1+bound, because, in the particular example of
s0.duration = 0, s1.duration = 0 and s2.duration = 3, it will try to add 1 + 1 + 4 to total_duration, as that is the state's bound + 1.
However, if I check the trace there's no point where total_duration exceed 3. I have checked the followed specs:
-- specification AG total_duration < 4 is true
-- specification F total_duration = 4 is false
-- specification EF total_duration >= 4 is false
How can I fix this? Either by declaring duration in another way or changing anything else?
The software does something very simple. It takes the domain of each addend, and checks whether the result variable would be able to hold the result of every possible combination of value. In this case:
the domain of s0.duration is 0..1
the domain of s1.duration is 0..1
the domain of s2.duration is 0..4
so, in principle, the maximum total_duration could be 6 and its domain should thus be 0..6. Therefore:
DEFINE
max_duration := s0.bound + s1.bound + s2.bound + 3
You may want to run NuSMV with the following option:
-keep_single_value_vars
Does not convert variables that have only one
single possible value into constant DEFINEs
In this way, you'll be able to run the model without having to add +1 to the domain of bound.
I want to create a define constant that is assigned to one of multiple otherdefine constants that has the largest value. Something like:
`define MAXWIDTH $MAX(`WIDTH0,`WIDTH1,`WIDTH2)
Is this possible in Verilog/SystemVerilog?
Depending on exactly what you need, there are a few ways to do it (there is no builtin call for maximum like in other languages):
You have some vectors and you need to get the maximum width for a new vector
$bits(v1 + v2 + v3 ...)
Use the language to your advantage, noting that the addition of vectors results in a vector that has the maximum width of all the operand vector widths and use $bits to get that size. Example:
logic [1:0] x;
logic [7:0] y;
logic [10:6] z;
...
max = $bits(x + y + z); // Result: max = 8
You have a few numbers of which you need the maximum
If you put your numbers in an array or queue, you can use the max method to get the largest:
int x[] = '{n1, n2, n3, ...};
...
max = x.max;
Note that this approach has the downside that it cannot be used at compile time for getting the maximum size. Example:
int _nums[] = '{13, 2, 17, 8, -1};
...
max = _nums.max; // Result: max = 17
Basically any other time
You'll just have to use the conditional operator, either in a macro or using let:
`define max2(v1, v2) ((v1) > (v2) ? (v1) : (v2))
`define max3(v1, v2, v3) `max2((v1), `max2((v2), (v3)))
OR
let max2(v1, v2) = (v1 > v2) ? v1 : v2;
let max3(v1, v2, v3) = max2(v1, max2(v2, v3));
The advantage of macros is that you can use them as compile-time constants in a wider range of tools, while older tools might not support let as a compile-time constant (or at all). Example:
max = `max3(10, 2, 3); // Result: max = 10
OR
max = max3(10, 2, 3); // Result: max = 10
Using the ROW-DISPLAY trigger when creating a dynamic OpenEdge browse. The problem is, when the data is displayed, all rows have the BGCOLOR determined by the data buffer's content of the LAST row only. Never had this problem with a static browse.
Browse code looks like this:
CREATE BROWSE l-browse-wh IN WIDGET-POOL "pool"
ASSIGN X = 1
Y = l-browse-y
FONT = INT(get-fn("browsedat-fnt"))
HEIGHT-PIXELS = l-h
WIDTH-PIXELS = FRAME f-data:WIDTH-PIXELS - 20
QUERY = hQuery
HIDDEN = FALSE
ROW-HEIGHT-CHARS = 0.67
READ-ONLY = FALSE
ROW-MARKERS = FALSE
SEPARATORS = TRUE
COLUMN-RESIZABLE = TRUE
COLUMN-SCROLLING = TRUE
FIT-LAST-COLUMN = FALSE
SCROLLBAR-VERTICAL = FALSE
FRAME = FRAME f-data:HANDLE
VISIBLE = TRUE
SENSITIVE = TRUE
TRIGGERS:
ON ROW-DISPLAY
PERSISTENT RUN row-color-ip IN THIS-PROCEDURE.
END TRIGGERS.
PROCEDURE row-color-ip:
DEF VAR l-bgcolor AS INT NO-UNDO.
IF tt-sold.t-exclude-sw /* <-- always uses value from last browse row */
THEN ASSIGN l-bgcolor = 8.
ELSE ASSIGN l-bgcolor = 15.
FOR EACH tt-col-handles
NO-LOCK:
ASSIGN tt-col-handles.t-wh:BGCOLOR = l-bgcolor.
END. /* of "FOR EACH tt-col-handles" */
END PROCEDURE.
It's something with your code (the part you're not showing). I used 10.2B Windows and replicated your code, filling the blanks. This little program alternates the colors, as I expected.
DEFINE VARIABLE l-browse-wh AS HANDLE NO-UNDO.
DEFINE VARIABLE hQuery AS HANDLE NO-UNDO.
define temp-table tt-sold
field cod as int
field name as char
field t-exclude-sw as logical.
create query hQuery.
hQuery:set-buffers(temp-table tt-sold:default-buffer-handle).
hQuery:query-prepare('for each tt-sold').
define temp-table tt-col-handles
field i as int
field t-wh as handle.
create widget-pool 'pool'.
define frame f-data with size 75 by 20.
CREATE BROWSE l-browse-wh IN WIDGET-POOL "pool"
ASSIGN X = 1
width = 60
height = 10
QUERY = hQuery
HIDDEN = FALSE
ROW-HEIGHT-CHARS = 0.67
READ-ONLY = FALSE
ROW-MARKERS = FALSE
SEPARATORS = TRUE
COLUMN-RESIZABLE = TRUE
COLUMN-SCROLLING = TRUE
FIT-LAST-COLUMN = FALSE
SCROLLBAR-VERTICAL = FALSE
FRAME = FRAME f-data:HANDLE
VISIBLE = TRUE
SENSITIVE = TRUE
TRIGGERS:
ON ROW-DISPLAY
PERSISTENT RUN row-color-ip IN THIS-PROCEDURE.
END TRIGGERS.
create tt-sold.
assign tt-sold.cod = 1 tt-sold.name = 'ABC' tt-sold.t-exclude-sw = yes.
create tt-sold.
assign tt-sold.cod = 2 tt-sold.name = 'DEF' tt-sold.t-exclude-sw = no.
create tt-sold.
assign tt-sold.cod = 3 tt-sold.name = 'GHI' tt-sold.t-exclude-sw = yes.
create tt-sold.
assign tt-sold.cod = 4 tt-sold.name = 'JKL' tt-sold.t-exclude-sw = no.
create tt-col-handles.
assign tt-col-handles.i = 1 tt-col-handles.t-wh = l-browse-wh:add-like-column('tt-sold.cod').
create tt-col-handles.
assign tt-col-handles.i = 2 tt-col-handles.t-wh = l-browse-wh:add-like-column('tt-sold.name').
create tt-col-handles.
assign tt-col-handles.i = 3 tt-col-handles.t-wh = l-browse-wh:add-like-column('tt-sold.t-exclude-sw').
hQuery:query-open().
l-browse-wh:refresh().
wait-for close of this-procedure.
PROCEDURE row-color-ip:
DEF VAR l-bgcolor AS INT NO-UNDO.
IF tt-sold.t-exclude-sw /* <-- always uses value from last browse row */
THEN ASSIGN l-bgcolor = 8.
ELSE ASSIGN l-bgcolor = 15.
FOR EACH tt-col-handles
NO-LOCK:
ASSIGN tt-col-handles.t-wh:BGCOLOR = l-bgcolor.
END. /* of "FOR EACH tt-col-handles" */
END PROCEDURE.
I apologize for the large chunk, but I couldn't just put my finger on where you're going wrong. Maybe this example will help you in some way. Hope it helps!
I want to write verilog code for Clarke and Park transformations for the implementation of a foc algorithm. I am new to verilog and I am failing to understand how to write the code for such complex equations which involve cos,sin functions and real numbers. Can someone please give me a start? The verilog code I tried to write is below.
timescale 1ns/1ps
module clarke_park(iR_i,iY_i,iB_i,theta,iD_o,iQ_o);
output real iD_o;
output real iQ_o;
input real iR_i;
input real iY_i;
input real iB_i;
real k = 0.66;
output real ialpha;
output real ibeta;
output real iY_r;//real part
output real iY_c;//complex part
output real iB_r;
output real iB_c;
output real ibeta_r;
output real ibeta_c;
function sin(input real theta);
function cos(input real theta);
iY_r = -1*(iY_i)*(0.5);
iY_c = (iY_i)*(0.866);
iB_r = -1*(iB_i)*(0.5);
iB_c = -1*(iB_i)*(0.866);
ialpha = k*iR;
ibeta_r = k*(0.866)*(iY_r-iB_r);
ibeta_c = k*(0.866)*(iY_c-iB_c);
real a1 = sin(theta);
real a2 = cos(theta);
iD_r = (a1*(ialpha)) + ((sin(theta))*(ibeta_r));
iD_c = a2*(ibeta_c);
iQ_r = - (1*a2*(ialpha)) + (a1*(ibeta_r));
iQ_c = a1*(ibeta_c);
endfunction
assign iD_o = {iD_r,iD_c};
assign iQ_o = {iQ_r,iQ_c};
endmodule
I would start with something like this:
module clarke_park(
output real iD_o,
output real iQ_o,
input real iR_i,
input real iY_i,
input real iB_i,
output real ialpha,
output real ibeta,
output real iY_r,//real part
output real iY_c,//complex part
output real iB_r,
output real iB_c,
output real ibeta_r,
output real ibeta_c
);
localparam k = 0.66;
Not sure what you are trying to do with the functions. but something like:
but note you have not defined theta, it was in you port list but then not defined as input or a real.
real a1;
real a2;
always #* begin
iY_r = -1*(iY_i)*(0.5);
iY_c = (iY_i)*(0.866);
iB_r = -1*(iB_i)*(0.5);
iB_c = -1*(iB_i)*(0.866);
ialpha = k*iR;
ibeta_r = k*(0.866)*(iY_r-iB_r);
ibeta_c = k*(0.866)*(iY_c-iB_c);
a1 = $sin(theta);
a2 = $cos(theta);
iD_r = (a1*(ialpha)) + ((sin(theta))*(ibeta_r));
iD_c = a2*(ibeta_c);
iQ_r = - (1*a2*(ialpha)) + (a1*(ibeta_r));
iQ_c = a1*(ibeta_c);
end
$cos and $sin are described in section 20.8 of ieee 1800-2012.
I am looking for a way to store a few variables in one variable so I can output a string. For example, I have variables:
int flow_val = "128";
int numb_val = "104";
int size_val = "256";
I can put them together using $display like this:
$display("32'h%0h%0h_%4h", flow_val, numb_val, size_val);
to print out:
32'h8068_0100
Is there a way to get that output and put it into a variable such as hex_val?
$sformatf can be used. Refer to IEEE Std 1800-2012, section 21.3.3 Formatting data to a string.
module tb;
int flow_val = 128;
int numb_val = 104;
int size_val = 256;
string hex_val;
initial begin
hex_val = $sformatf("32'h%0h%0h_%4h", flow_val, numb_val, size_val);
$display(hex_val);
end
endmodule
Output:
32'h8068_0100