assignment in SystemVerilog, compilation error - token is 'assign' - system-verilog

I have this code:
integer [31:0]R;
integer [15:0]R_f1;
integer [15:0]R_f2;
assign R_f1 = R[15:0];
assign R_f2 = R[31:16];
But it is not compiled because of assign.
What changes do I need to do ? It can also be in the header file.

There was a bug in the original implementation of Verilog-XL that it ignored the packed dimensions of integer declarations. And integer/int/byte did not have a fixed size. For these reasons, SystemVerilog disallows specifying packed dimensions for any of these built-in types. Use bit or logic instead.
Also, since you tagged this with SystemVerilog make sure the file has a *.sv suffix. An alternative to what you are trying to do is
integer [31:0]R;
let R_f1 = R[15:0];
let R_f2 = R[31:16];

Depending on the language you use. In verilog, only the net types can be assigned using continuous assignment. integer is not a net type, therefore theses assignments are not allowed in verilog. I guess you compiled your code in verilog mode and got the message about assignment statements.
Also packed dimensions on integer types are not allowed. So, the following declaration is illegal: integer [31:0]R;. Some compilers will just ignore the declaration. All integers are 32 bit wide in any case.
So, to fix it in verilog mode you can use always #* instead:
integer R = 10;
integer R_f1;
integer R_f2;
always #* R_f1 = R[15:0];
always #* R_f2 = R[31:16];
Though by the sound of your initial question, you need to use a different type of the data type, which allows you to have real vectors. In verilog they are reg and one of the net types, i.e. wire. With wires you can use assign statement, with reg you need to use always blocks. Something like the following:
reg[31:0] R = 10;
reg[15:0] R_f1;
reg[15:0] R_f2;
always #* R_f1 = R[15:0];
always #* R_f2 = R[31:16];
Since you marked your question as a system verilog question, you can use one of the system verilog types, i.e. logic or bit. If you use those, you can apply both, assign or always blocks to them. BTW, assign will also work for integeres.
logic[31:0] R = 10;
logic[15:0] R_f1;
logic[15:0] R_f2;
assign R_f1 = R[15:0];
assign R_f2 = R[31:16];
just make sure that you compile in a system-verilog mode.

Related

When subclassing "double" with new properties in MATLAB, is there an easy way to access the data value?

Say I have a class subclassing double, and I want to add a string (Similar to the 'extendDouble' in the documentation). Is there an easy way to access the actual numeric value without the extra properties, particular for reassigning? Or if I want to change the value, will I have to recreate the value as a new member of the class with the new value and the same string?
e.g.
classdef myDouble < double
properties
string
end
methods
function obj = myDouble(s)
% Construct object (simplified)
obj.string = s;
end
end
end
----------
x = myDouble(2,'string')
x =
2 string
x = 3
x =
3 string
Short answer: NO. There is no easy way to access a single member of a class when the class contains more than one member. You'll always have to let MATLAB know which part of the class you want to manipulate.
You have multiple questions in your post but let's tackle the most interesting one first:
% you'd like to instanciate a new class this way (fine)
x = myDouble(2,'string')
x =
2 string
% then you'd like to easily refer to the only numeric part of your class
% for assignment => This can NEVER work in MATLAB.
x = 3
x =
3 string
This can never work in MATLAB because of how the interpreter works. Consider the following statements:
% direct assignment
(1) dummy = 3
% indexed assignments
(2) dummy(1) = 3
(3) dummy{1} = 3
(4) dummy.somefieldname = 3
You would like the simplicity of the first statement for assignment, but this is the one we cannot achieve. The statement 2, 3 and 4 are all possible with some fiddling with subasgn and subsref.
The main difference between (1) and [2,3,4] is this:
Direct assignment:
In MATLAB, when you execute a direct assignment to a simple variable name (without indexing with () or {} or a field name) like dummy=3, MATLAB does not check the type of dummy beforehand, in fact it does not even check whether the variable dummy exists at all. No, with this kind of assignment, MATLAB goes the quickest way, it immediately create a new variable dummy and assign it the type and value accordingly. If a variable dummy existed before, too bad for it, that one is lost forever (and a lot of MATLAB users have had their fingers bitten once or twice by this behavior actually as it is an easy mistake to overwrite a variable and MATLAB will not raise any warning or complaint)
Indexed assignments:
In all the other cases, something different happens. When you execute dummy(1)=3, you are not telling MATLAB "create a new dummy variable with that value", you are telling MATLAB, "find the existing dummy variable, find the existing subindex I am telling you, then assign the value to that specific subindex". MATLAB will happlily go on, if it finds everything it does the sub-assignment, or it might complains/error about any kind of misassignment (wrong index, type mismatch, indices length mismatch...).
To find the subindex, MATLAB will call the subassgn method of dummy. If dummy is a built-in class, the subassgn method is also built in and usually under the hood, if dummy is a custom class, then you can write your own subassgn and have full control on how MATLAB will treat the assignment. You can check for the type of the input and decide to apply to this field or another if it's more suitable. You can even do some range check and reject the assignment altogether if it is not suitable, or just assign a default value. You have full control, MATLAB will not force you to anything in your own subassgn.
The problem is, to trigger MATLAB to relinquish control and give the hand to your own subassgn, you have to use an indexed assignment (like [2,3 or 4] above). You cannot do that with type (1) assignment.
Other considerations: You also ask if you can change the numeric part of the class without creating a new object. The answer to that is no as well. This is because of the way value classes work in matlab. There could be a long explanation of what happens under the hood, but the best example is from the MATLAB example you referenced yourself. If we look at the class definition of ExtendDouble, then observe the custom subassgn method which will perform the change of numeric value, what happens there is:
obj = ExtendDouble(b,obj.DataString);
So even Mathworks, to change the numeric value of their extended double class, have to recreate a brand new one (with a new numeric value b, and transfering the old string value obj.DataString).

any way how to define msb:lsb range as parameter?

having tons of registers defined in my hardware, containing bit fields, I wanted to 'name' those registers and access in SystemVerilog the bit fields using their names instead of msb:lsb format. So, I made a new package, and declared constant parameters inside, and as well tried those which describe range. Something like this:
package VmeAddressMap;
parameter SYS_INTCONFIG = 32'h00000044;
parameter RSYS_INTCONFIGRORA = 31:16;
parameter RSYS_INTCONFIGENABLE = 15:0;
endpackage // VmeAddressMap
quite evidently, this does not work. So I came with a 'hybrid' solution, i.e. simple constants stay in package, and for ranges I made another file, which contains macros:
package file:
package VmeAddressMap;
parameter SYS_INTCONFIG = 32'h00000044;
endpackage // VmeAddressMap
macro file:
`define RSYS_INTCONFIGRORA 31:16
`define RSYS_INTCONFIGENABLE 15:0
this solution permits me to do things as follow (Read is a task reading data through VME bus):
Read(SYS_INTCONFIG);
`CHECK_EQUAL(LastVmeReadData_b32[`RSYS_INTCONFIGRORA], 15,
"IRQ setup invalid");
This works, and does what I want. However I don't like it. In particular mixing macros with SystemVerilog style of description.
Is there a way how to accomplish the same task directly in the package?
This is exactly what the UVM register abstraction layer does for you. You define fields giving them a name, bit width, and other attributes. Those fields are grouped into a registers, and registers are grouped into blocks with addresses and offsets.
Now that I've told you that, here's a simple solution that does what you are looking for using the let construct.
package VmeAddressMap;
parameter SYS_INTCONFIG = 32'h00000044;
let RSYS_INTCONFIGRORA(field) = field[31:16];
let RSYS_INTCONFIGENABLE(field) = field[15:0];
endpackage // VmeAddressMap
But now you have to put the range in front of the variable.
`CHECK_EQUAL(RSYS_INTCONFIGRORA(LastVmeReadData_b32), 15,
"IRQ setup invalid");
You can use one parameter for the MSB and another for the LSB.
parameter RSYS_INTCONFIGRORA_MSB = 31;
parameter RSYS_INTCONFIGRORA_LSB = 16;
LastVmeReadData_b32[RSYS_INTCONFIGRORA_MSB:RSYS_INTCONFIGRORA_LSB]
That is a bit unwieldy, so if everything is 16 bits wide you can just define the LSB:
parameter RSYS_INTCONFIGRORA = 16;
LastVmeReadData_b32[RSYS_INTCONFIGRORA +: 16]
Or, you can use a struct:
typedef struct packed {
logic [15:0] RSYS_INTCONFIGRORA;
logic [15:0] RSYS_INTCONFIGENABLE;
} some_register_t;
You can further make a union with that struct if some parts of the design need to interact with the whole register object and others with just the bit fields.
These register structs can be built up into a much larger register map struct.
If you are using UVM then you should be building up a RAL module of your registers

how single and double type variables work in the same copy of code in Matlab like template in C++

I am writing a signal processing program using matlab. I know there are two types of float-pointing variables, single and double. Considering the memory usage, I want my code to work with only single type variable when the system's memory is not large, while it can also be adapted to work with double type variables when necessary, without significant modification (simple and light modification before running is OK, i.e., I don't need runtime-check technique). I know this can be done by macro in C and by template in C++. I don't find practical techniques which can do this in matlab. Do you have any experience with this?
I have a simple idea that I define a global string containing "single" or "double", then I pass this string to any memory allocation method called in my code to indicate what type I need. I think this can work, I just want to know which technique you guys use and is widely accepted.
I cannot see how a template would help here. The type of c++ templates are still determined in compile time (std::vector vec ...). Also note that Matlab defines all variables as double by default unless something else is stated. You basically want runtime checks for your code. I can think of one solution as using a function with a persistent variable. The variable is set once per run. When you generate variables you would then have to generate all variables you want to have as float through this function. This will slow down assignment though, since you have to call a function to assign variables.
This example is somehow an implementation of the singleton pattern (but not exactly). The persistent variable type is set at the first use and cannot change later in the program (assuming that you do not do anything stupid as clearing the variable explicitly). I would recommend to go for hardcoding single in case performance is an issue, instead of having runtime checks or assignment functions or classes or what you can come up with.
function c = assignFloat(a,b)
persistent type;
if (isempty(type) & nargin==2)
type = b;
elseif (isempty(type))
type = 'single';
% elseif(nargin==2), error('Do not set twice!') % Optional code, imo unnecessary.
end
if (strcmp(type,'single'))
c = single(a);
return;
end
c = double(a);
end

How to pass a variable value to a macro in SystemVerilog?

I think the question sums it up pretty well as to what I want: passing the value of a variable to a macro in SystemVerilog.
For example, what I want:
Say, there are 4 signals by the name of abc_X_def and I want to initialize all of them to 0.
So, without macros:
abc_0_def = 4'b0000;
abc_1_def = 4'b0000;
abc_2_def = 4'b0000;
abc_3_def = 4'b0000;
Now, the code that I have written is having a problem:
`define set_value(bit) abc_``bit``_def = 4'b0000
for (int i = 0; i < 4; i++) begin
`set_value(i);
end
The error is that it's trying to find the signal abc_i_def which is obviously wrong. Just wondering if it's possible to pass the actual value of the variable 'i' to the macro.
The preprocessor directives are evaluated by the preprocessor and modify the code that is presented to the compiler.
The for loop is a verilog construct that is evaluated by the compiler.
So your preprocessor is not evaluating the for loop. It sees:
`define `set_value(bit) abc_``bit``_def = 4'b0000
[some verilog]
`set_value(i);
[some verilog]
So 'i' is just i. It doesn't become a number until compilation.
Why don't you use local params with generate, so the local params are created in a loop at elaboration as the for loop is unrolled?
This is one of the many places that macros are a problem. Generate is a problem in other places (like when you want to control port lists).
I dug into this a bit more. Parameters and local parameters inside a generate are created a localparams in the scope of the generate. See here: System Verilog parameters in generate block. I had to get back to work before I could test it.
I would just use code and populate an array. This compiles in VCS:
module veritest
#(
parameter MAX_X = 5,
MAX_Y = 3,
MAX_Z = 2
)
(); // empty port list
logic [4:0] abc_def[1:MAX_X][1:MAX_Y][1:MAX_Z];
always #*
begin
for (integer z=1; z<(MAX_X+1);z=z+1)
for (integer y=1; y<(MAX_Y+1);y=y+1)
for (integer x=1; x<(MAX_X+1);x=x+1)
begin
abc_def[x][y][z] = 4'b0000;
end
end
endmodule
Since you said the naming conventions is out of your control, you should consider using another tool to generate the verilog for you.
You can have the code generated by your preferred programming then use an `include statement in your verilog file. Or you can go with an embedded route.
Perl had EP3 : http://search.cpan.org/~gspivey/Text-EP3-Verilog-1.00/Verilog.pm
Ruby has eRuby : http://www.tutorialspoint.com/ruby/eruby.htm
I'm sure something like it exists for other languages to. Such as Python, Tcl, JavaScript, etc.
Concept is the same, just a difference in embedded language and tool used for conversion.

How do I access memory addresses directly in Ada?

So I'm new to Ada, and I'm attempting to write a kernel in it, but I cannot seem to find any good information on how to do this properly. In C, I would write:
unsigned char* videoram = (char*) 0xB8000;
videoram[0] = 65;
to access the video ram directly and write 'a' to it. I've heard I need to use an Ada array and other pragma's to do this in a typesafe manner in Ada. Is there any good resources on this kind of Ada programming?
You can use the 'Address attribute:
Videoram : String (1 .. Videoram_Size);
for Videoram'Address use 16#B8000#;
-- ...
Videoram (1) := 'a';
If you don't want to use String and Characters, you can define your own data types.. like:
type Byte is mod 2**8; -- unsigned char
type Byte_Array is array (Natural range <>) of Byte;
Videoram : Byte_Array (0 .. Videoram_Size - 1);
for Videoram'Address use 16#B8000#;
-- ...
Videoram (0) := 65;
Btw, you even get range checking for the index, so you can't write outside of the Videoram range.
If you use an address attribute (i.e. for Object'Address use ... ), you should use the To_Address() function found in System.Storage_Elements because the Address type doesn't have to be an integer. The Ada Reference Manual only states:
"Address is a definite, nonlimited type with preelaborable initialization"
Whereas for the Integer_Address type in System.Storage_Elements it states:
"Integer_Address is a (signed or modular) integer subtype. To_Address and To_Integer convert back and forth between this type and Address."
So, you should really use:
for Object'Address use To_Address( 16#B8000# );
One last thing to point out from T.E.D's answer is that if you are concerned about object initialization using this method, simply add a pragma Import( Ada, your_object ) after the declaration so that default initialization is suppressed.
There are actually two ways.
One is to set a pointer to the address you want to use, and access the object via the pointer.
type Video_RAM_Pointer is access all My_Video_Ram_Struct;
package Convert is new System.Address_To_Access_Conversions (Video_RAM_Pointer);
Video_RAM : constant Video_RAM_Pointer := Convert.To_Access (16#B8000#);
The other is to overlay your data right on top of the location.
Video_RAM : My_Video_RAM_Struct;
for Video_RAM'address use at 16#B8000#;
Generally, I prefer using the former. Among other issues, the latter counts as a declaration, which means that any fields in My_Video_RAM_Struct that have initialization code will get reinitialized every time you declare your overlay. Additionally, it is tempting to folks to overuse (abuse) that feature to alias objects all over the place, which is both hard on the optimizer and hard on the maintanence programmer.
The pointer method just tells the compiler to assume the given address holds the structure you told it, which IMHO is exactly what you want to happen.