Verilog specify block within for-loop - verilog

I am trying to model path delays for an n-bit wide signal. I can do this fine if I explicitly define the delay for each individual bit, like this (n=3):
specify
(in_data[0] => delayed_data[0]) = 5;
(in_data[1] => delayed_data[1]) = 2;
(in_data[2] => delayed_data[2]) = 1;
endspecify
However, I want to be able to specify random delays for each bit of in_data when in_data is n-bits wide. My idea was something like this:
for (n=0;n<DATA_WIDTH-1;n=n+1)
begin
specify
(in_data[n] => delayed_data[n]) = {$random};
endspecify
end
This gives me an error: "near 'specify': syntax error, unexpected specify"
I also tried placing the for loop within the specify block. This resulted in the following error: "near 'begin': syntax error, unexpected begin, expecting endspecify"
I would really appreciate any tips on how to do this correctly

According to the Doulos Verilog Reference Guide (page 84) a specify block can only occur within module and endmodule tags, and not within anything else.
According to this Verilog reference website:
The Specify block was designed to define a delay across a module. It starts with specify and ends with the endspecify keyword. Inside the block the user can specify: specparam declaration, path declaration or system timing check.
This seems to imply it does not allow for-loops within specify blocks.
Hence it leads me to believe that you'll need to write out all the values one by one due to a limitation of the language.
One idea you could try is to restructure your modules to have a one bit input to a one bit output. Then each specify block will only have one delay to specify, and you can assign them each a random value. You can then generate these modules inside a generate block which will avoid you having to specify a delay for each bit manually.
However, this may be more tedious/awkward.

Related

Dalvik bytecode instrumentation - register type merging

I am doing some sort of dalvik bytecode instrumentation using dexlib2.
However, there are a couple of remaining issues.
The register type merging that seems to happen after goto instructions
and catch blocks, more precisely at the corresponding label, somehow
derives an unexpected register type, which in turn breaks the instrumented code.
The instructions that get inserted look as follows:
move(-wide,-object,/16,/from16) vNew, v0
const-string v0, "some string"
invoke-static, {v0}, LPathToSomeClass;->SomeMethod(Ljava/lang/String;)V
move(..) v0, vNew
So, v0 is used to hold some parameter for the static function call, while
vNew is a new (local) register to store and restore the original content of v0. The register type of v0 is derived in advance in order to derive the right
move instruction, i.e. move-wide, move or move-object. However, when this code is included within some try-block, the instrumentation breaks. The output of
baksmali (baksmali d -b "" --register-info ALL,FULLMERGE --offsets )
reveals that the type of v0 after the const-string instruction (which is Reference,L/java/lang/String) is considered as input for the merging procedure happening for instance at the corresponding catch-block label. Assuming that the type before the inserted code was Reference,[I (int array) the resulting
type is now Reference,L/java/lang/Object (which produces a verification error), although the final move instruction restores the original register type.
Now to my questions:
1) When is this merging actually happening?
2) Why is the merging procedure considering the type of v0 after the const-string instruction? Is it considering every instruction modifying the type of any register?
3) Is this problem only related to try-catch blocks?
4) What are the restrictions for try-catch blocks in this matter?
5) Is there any solution to this problem apart from constructing an own method for each code to inject without parameters? So is it possible to use an additional register to solve this problem?
6) Can I detect with dexlib2 try-catch blocks and determine the set of instructions they include?
7) Are there any notes/literature discussing this problem, e.g. the merging procedure, and related technicalities, e.g. further limitations/restrictions
for the instrumentation?
I highly appreciate any help in this matter. Thanks in advance!
When merging registers at the start of a catch block, there is an incoming edge from every instruction in the try block that can throw. Only certain instructions can throw - as determined by the CAN_THROW opcode flag.
In your particular example, the invoke-static instruction after the const-string instruction can throw, and so there's an edge from just before that instruction to the start of the catch block.
If you take a step back, execution can jump from any instruction in the try block that can throw to the start of the catch block. And so the code in the catch block must be prepared for the registers to be in a state that is consistent with the register contents just before any of those instructions that can throw.
So, for example, if there is one possible "jump" from the try block to the catch block where the register contains an primitive int type, and another possible jump where it contains an object, that register is considered "conflicted", because the the register may contain either type at that point in the code, and the two types are not compatible with each other. E.g. a primitive int can never be passed to something expecting a reference type and vice versa. And there's no mechanism in the bytecode for static register type checking.
One possible solution might be to split the try block at the point where you insert your instrumentation, so that the instrumentation itself is not covered by a try block, but both "sides" of the original code is. And keep in mind that in the bytecode, the same catch block can be used by multiple try blocks, so you can split the original try block into two, and have both reference the original catch block.
Otherwise, you'll just have to figure out some way to manage the registers appropriately to avoid this problem.
As for 6), see MethodImplementation.getTryBlocks(), which will give you a list of try blocks in that method. Each try block specifies where it starts, how many instructions it covers, and all of the catch blocks associated with it (different catch blocks for different exceptions).

How does SystemVerilog `force` work?

I have a hierarchy of modules where I am trying to do a force to get different value at different module interface. I am working on a component whose task is to inject transaction to a module down the hierarchy, bypassing the drives from the modules higher up in the hierarchy. I thought I could use force on the control signals in order to disengage drives from higher up modules and start driving into the module of interest. So I have been trying to see how force will work. The full code is at http://www.edaplayground.com/x/69PB.
In particular, I am trying to understand effect of these two statements within initial block:
force u_DataReceiveTop.u_DataReceiveWrap.DataReceiveIfWrp_inst.valid = 1'b0;
force u_DataReceiveTop.valid = 1'b1;
what I expected the values to be is:
u_DataReceiveTop.u_DataReceiveWrap.DataReceiveIfWrp_inst.valid == 0
u_DataReceiveTop.valid == 1
but I see from waves:
u_DataReceiveTop.u_DataReceiveWrap.DataReceiveIfWrp_inst.valid == 1
u_DataReceiveTop.valid == 1
It is as if the second force statement force u_DataReceiveTop.valid = 1'b1; has propagated down the hierarchy even though there is another force. What is happening here?
A wire in Verilog is a network of drivers and receivers all connected to the same signal. The value of that signal is some resolution function of all the drivers and the type of the wire. When you connect two wires through a port, the two wires get collapsed into a single signal, but you still have two different names for the same signal.
When you use the force statement on a wire, that overrides all the drivers on the network until encountering another force or release statement. In your example, the second force statement replaces the first force. I doesn't matter which hierarchical reference you use in the force because they all refer to the same signal.
If you want the behavior you are expecting, you need to use variables instead of wires. When you connect a variable to a port, SystemVerilog creates an implicit continuous assignment, depending on the direction of the port. SystemVerilog does not allow more than one continuous assignment to a variable, which is why you can't use variables with an inout port. So you will need to be more careful about the port directions then.

Parameterized FIFO instantiation in Verilog

I wanted to have a parameterized FIFO instantiation so that I can call a single FIFO instance with change in depth(parameter).
e.g. I have written a code for FIFO with depth as a parameter.
I will know the depth of the FIFO only by the configuration from Microprocessor. Based on the register configuration, can i call this FIFO with variable parameter like value?
integer depth_param;
if(config_reg[1])
depth_param <= 128;
else
depth_param <= 512;
genfifo #(depth_param) (.din (din),.wr(wr)....);
fifo module is:
module gen_fifo #(depth = 128)
( din,wr,rd,clk....);
can you please suggest is there a way I can do this?
This is what the LRM says:
Parameters represent constants; hence, it is illegal to modify their
value at run time. However, module parameters can be modified at
compilation time to have values that are different from those
specified in the declaration assignment. This allows customization of
module instances. A parameter can be modified with the defparam
statement or in the module instance statement. Typical uses of
parameters are to specify delays and width of variables.
'run time' means during simulation, after elaboration. A synthesiser doesn't 'run' anything, but what you're doing is effectively "run time", and so is illegal.
This doesn't mean that you can't do it, though. Pass in your FIFO depth as a module port. I'm assuming that you know how to code a FIFO from first principles. If so, you will normally have a constant for the FIFO size; just replace this constant with the value at the port, and find some way to set the memory size. You'll obviously need to be careful when changing the FIFO size - you may need to reset it, for example. If you don't know how to code a FIFO you should ask with an FPGA or an electronics tag.

Verilog doesn't have something like main()?

I understand that modules are essentially like c++ functions. However, I didn't find something like a main() section that calls those functions. How does it work without a main() section?
Trying to find (or conceptually force) a main() equivalent in HDL is the wrong way to go about learning HDL -- it will prevent you from making progress. For synthesisable descriptions you need to make the leap from sequential thinking (one instruction running after another) to "parallel" thinking (everything is running all the time). Mentally, look at your code from left to right instead of top to bottom, and you may realize that the concept of main() isn't all that meaningful.
In HDL, we don't "call" functions, we instantiate modules and connect their ports to nets; again, you'll need to change your mental view of the process.
Once you get it, it all becomes much smoother...
Keep in mind that the normal use of Verilog is modeling/describing circuits. When you apply power, all the circuits start to run, so you need to write your reset logic to get each piece into a stable, usable operating state. Typically you'll include a reset line and do your initialization in response to that.
Verilog has initial blocks are kinda like main() in C. These are lists of statements that are scheduled to run from time 0. Verilog can have multiple initial blocks though, that are executed concurrently.
always blocks will also work as main() if they've an empty sensitivity list:
always begin // no sensitivity list
s = 4;
#10; // delay statements, or sim will infinite loop
s = 8;
#10;
end

Verilog automatic task

What does it mean if a task is declared with the automatic keyword in Verilog?
task automatic do_things;
input [31:0] number_of_things;
reg [31:0] tmp_thing;
begin
// ...
end
endtask;
Note: This question is mostly because I'm curious if there are any hardware programmers on the site. :)
"automatic" does in fact mean "re-entrant". The term itself is stolen from software languages -- for example, C has the "auto" keyword for declaring variables as being allocated on the stack when the scope it's in is executed, and deallocated afterwards, so that multiple invocations of the same scope do not see persistent values of that variable. The reason you may not have heard of this keyword in C is that it is the default storage class for all types :-) The alternatives are "static", which means "allocate this variable statically (to a single global location in memory), and refer to this same memory location throughout the execution of the program, regardless of how many times the function is invoked", and "volatile", which means "this is a register elsewhere on my SoC or something on another device which I have no control over; compiler, please don't optimize reads to me away, even when you think you know my value from previous reads with no intermediate writes in the code".
"automatic" is intended for recursive functions, but also for running the same function in different threads of execution concurrently. For instance, if you "fork" off N different blocks (using Verilog's fork->join statement), and have them all call the same function at the same time, the same problems arise as a function calling itself recursively.
In many cases, your code will be just fine without declaring the task or function as "automatic", but it's good practice to put it in there unless you specifically need it to be otherwise.
It means that the task is re-entrant - items declared within the task are dynamically allocated rather than shared between different invocations of the task.
You see - some of us do Verilog... (ugh)
The "automatic" keyword also allows you to write recursive functions (since verilog 2001). I believe they should be synthesisable if they bottom out, but I'm not sure if they have tool support.
I too, do verilog!
As Will and Marty say, the automatic was intended for recursive functions.
If a normal (i.e. not automatic) function is called with different values and processed by the simulator in the same time slice, the returned value is indeterminate. That can be quite a tricky bug to spot! This is only a simulation issue, when synthesised the logic will be correct.
Making the function automatic fixes this.
In computing, a computer program or subroutine is called re-entrant if multiple invocations can safely run concurrently (Wikipedia).
In simple words, the keyword automatic makes it safe, when multiple instances of a task run at a same time.
:D
Automatic is just opposite to static in usual programming. So is the case with Verilog. Think of static variables, they cannot be re-initialized. See the Verilog description below:
for (int i = 0; i < 3; i++) begin
static int f = 0;
f = f + 1;
end
Result of the above program will be f = 3. Also, see the program below:
for (int i = 0; i < 3; i++) begin
int f = 0;
f = f + 1;
end
The result of above program is f = 1. What makes a difference is static keyword.
Conclusion is tasks in Verilog should be automatic because they are invoked (called) so many times. If they were static (if not declared explicitly, they are static), they could have used the result from the previous call which often we do not want.

Resources