$fclose placement in testbench - verilog

I want to use $fmonitor so that an output value is written to a file every time the value changes.
When I place $fclose inside the initial begin block, there are no errors. However, unsurprisingly, the output file is empty.
When I place $fclose right before the endmodule statement, I get a syntax error. Where should I place it?
`timescale 1ns / 1ps
module fir168_input_ones_tb();
integer fp;
reg clk, rst;
wire tvalid, fir_valid, fir_rdy;
wire [15:0] inputdata;
wire signed [39:0] fir_out;
generateOnes indata(
.clk (clk),
.outData (inputdata),
.tlast (tvalid));
fir168 fir168_i
//(.M_AXIS_DATA_0_tdata(fir_out_trunc),
(.M_AXIS_DATA_0_tdata(fir_out),
.M_AXIS_DATA_0_tvalid(fir_valid),
.S_AXIS_DATA_0_tdata(inputdata),
.S_AXIS_DATA_0_tready(fir_rdy),
.S_AXIS_DATA_0_tvalid(tvalid),
.aclk_0(clk));
always begin
clk = ~clk; #5;
end
initial begin
fp = $fopen("simOutput.txt", "w+");
$fmonitorh(fp, fir_out);
clk = 0;
//$display("%d", fir_out);
//$fclose(fp);
end//initial
$fclose(fp);
endmodule

$fopen/$fmonitor/$fclose are all procedural statements that must be placed inside procedural code.
When you had $fclose in the initial block, you closed it at time 0 before $fmonitor had a chance to produce any output. $fmonitor writes the state of its arguments at then end of current time slot when any of them change value.
You need to let your simulation run for some period of time and then have it execute a $finish. There is no need to explicitly use $fclose unless you have too many files open at one time, or some other process is blocked waiting for the file output.

$fclose must be used inside a procedural block, like an initial block. That is why you get the syntax error when you place it right before endmodule.
If you want the file to be written until the end of the simulation, there is no need to call $fclose. The file will automatically be closed at the end of the sim.
Otherwise, you need to pick a specific time or a signal event and then close the file. But, keep in mind that $fmonitor will be active for the entire simulation. That means that if fir_out changes after you close the file, your simulator might generate error or warning messages.

$fmoniotor statement does not do much, except it schedules monitor events at the end of every simulation tick. As a result, the $fclose will close the file in the same time tick where $fmonitor was issued before the first execution of a scheduled monitor event.
initial begin
$fmonitor(...);
...
$fclose()
end
You can do several things:
Put a certain timing distance between $fmonitor and $fclose, giving a chance for simulation to do something before the file gets closed:
initial begin
$fmoniotor(..);
...
#1000 // add a simulation delay of some value before closing
$fclose(...);
end
you can place $fclose in the final block if you want to close it before exit:
initial begin
$fmonitor(...);
...
end
final begin
...
$fclose(...);
end
Or you can figure out some event scheme which will close your file when a certain event is generated.
initial
$fmonitor
always #* begin
if (condition)
$fclose()
end

Related

How is the program block controlling the clock output in this code?

This is a simple SV program (I know an arbiter is much more complex, pardon me for naming this as one), but I don't know how the line repeat(4) #ar.cb; keeps controlling the entire clock. If I comment out that line, the clock stops even though I have put it in an 'always' block inside the top module. I can't understand how this works.
testbench.sv
interface arb_if(input bit clk);
logic [1:0] request;
logic [1:0] grant;
logic reset;
clocking cb #(posedge clk);
output request;
input grant;
endclocking
modport DUT(input request,clk,reset,output grant);
modport TB(clocking cb,output reset); endinterface
program automatic test(arb_if.TB ar);
initial begin
ar.reset <= 1;
ar.cb.request<=$urandom;
$display("[%0t]Request is sent",$time);
repeat(4) #ar.cb;
$display("[%0t]Grant=%0d",$time,ar.cb.grant);
end endprogram
module top;
bit clk;
always #5 clk=~clk;
arb_if arb(clk);
test tb(arb);
arbit a1(arb,clk); endmodule
design.sv
module arbit(arb_if.DUT arbiter,input bit clk); always #(posedge clk)
if(arbiter.reset==0)
arbiter.grant<=2'bxx;
else
#1 arbiter.grant<=arbiter.request;
endmodule
And in the design, the grant does not get assigned till the next cycle even if I use a blocking assignment (unless I give #1, in which case it does, of course after the delay).
I am struggling with understanding the synchronous circuit timings. It'd be a great help if someone can clear this up for me.
Without #1:
With #1:
The program terminates the simulation.
From IEEE Std 1800-2017, section 24.3 The program construct:
When all initial procedures within a program have reached their end,
that program shall immediately terminate all descendent threads of
initial procedures within that program. If there is at least one
initial procedure within at least one program block, the entire
simulation shall terminate by means of an implicit call to the $finish
system task immediately after all the threads and all their descendent
threads originating from all initial procedures within all programs
have ended.
With the repeat statement, the simulation ends at time 35. It waits for 4 positive edges of clk, then implicitly calls $finish.
Without the repeat statement, the simulation ends at time 0. It doesn't wait for any clk edges, then implicitly calls $finish.

Approach to design valid/ready handshake

I have implemented valid/ready handshake signals in verilog. I just wanted to know if my approach is right or something is wrong. I shall be happy to know of any improvement.
A simple counter is used as an input to fifo. So when fifo is almost full which is declared when used word of fifo is 8 (8 stacks of fifo are used out of 16), ready is zero.
Here is the code.
module fifohandshake(
input CLK,
input RST,
input [31:0] INPUT,
output [31:0] OUTDATA,
output [3:0] usedword,
output Writereq,
input RDReq,
output Almost_full,
output EMPty,
output FUlL,
output VALID,
output READY
);
reg valid;
reg ready;
reg WRReq;
assign VALID=valid;
assign READY=ready;
assign Writereq=WRReq;
fifoip u0(
.clock(CLK),
.data(INPUT),
.rdreq(RDReq),
.sclr(RST),
.wrreq(WRReq),
.almost_full(Almost_full),
.empty(EMPty),
.full(FUlL),
.q(OUTDATA),
.usedw(usedword)
);
always #(posedge CLK)
begin
if(INPUT)
begin
valid<=1;
end
else
begin
valid<=0;
end
end
always #(posedge CLK)
begin
if(Almost_full)
begin
ready<=0;
end
else
begin
ready<=1;
end
end
always #(posedge CLK)
begin
if(ready)
begin
WRReq<=1;
end
else
begin
WRReq<=0;
end
end
endmodule
Have I done it in a right way or is there something that I need to correct? Here are the waveform results.
enter image description here
For those who think that I didn't put enough effort in my research. A finite state machine is a good approach to implement ready/valid handshake protocol. Few points have to be kept in mind
The valid signal doesn't depends upon ready signal. In other words there shouldn't be a combinational loop if you trace your logical circuit from valid to ready signal.
Three basic states can be defined for valid/ready protocol. First idol state where there is no valid data even though the slave is ready to accept data. Then, a transfer state where both ready and valid signals are high. And the third state is wait state where we have the valid signal high but ready signal is low.
A buffer (a fifo or a simple register) has to be used in the wait state to buffer the valid data in case the slave is no ready. Hence, data is not lost and is still on the data line whenever slave is again ready.
That's it....
This was the help that I was trying to ask from the community but from the last couple of days whenever I post something someone intentionally mark my question to be -1. I hope not to experience it next time...

Can we initialize variables with "nets", instead of a constant, within "initial" block?

The following code gives output ("fact") 1 irrespective of the input. What is the error?
module Factorial_calc(n, fact);
input [5:0] n;
output reg [64:0] fact;
reg [5:0] i;
initial
begin
i=n;
fact=1;
end
always #(*)
begin
while(i>0)
begin
fact=i*fact;
i=i-1;
end
end
Verilog will not stop you from assign a reg to a net's value within an initial block, but you are extremely unlikely to get the result you expect.
An initial block runs ones at time 0. The net may not have the intended value before it is assigned to the reg. By design, Verilog allows for non-determinism of the evaluation order of procedural blocks and contentious assignments within the same phase of a time-step. Verilog's evaluation order can be controlled by event dependency. initial blocks do not not event dependencies, so it will always be evaluated as soon as possible. Nets will have dependencies (unless they are assigned to constants) so the typically are evaluated later.
The minimum change to get your code to work is to move the content of the initial block to inside the always block above the while statement. This will update i every time input n changes and reset fact before it is updated in the while loop.
always #(*)
begin
i = n; // <-- local sample
fact = 1; // local reset
while(i>0)
begin
fact=i*fact;
i=i-1;
end
end
This will work for simulation, but it cannot synthesize because it used a while statement.

I have faced a problem with Verilog Multiplier Module

Picture given is a module I'd like to express.
MulCell
For some reason I had to bring up the Multiplicand or Multiplier from arrays of numbers using wire. ex)wire [3:0] abc = 4'b1111;
But very odd! When I assign specific value of wire abc to "Multiplier", it works well. However if I assign it to "Multiplicand", I see red lines just as in the picture. redline
Any idea what had gone wrong? Thanks
Code for MulCell
module MulCell(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
input Multiplicand,Multiplier,Sin,Cin;
output Sout,Cout;
reg Sout,Cout;
wire tmp;
assign tmp=Multiplicand&Multiplier;
always#(tmp) begin
{Cout,Sout} <= tmp+Sin+Cin;
end
endmodule
Code for testbench_MulCell
`timescale 1ns/1ns
module testbench_MulCell();
reg Multiplicand,Multiplier,Sin,Cin;
wire Sout,Cout;
MulCell MC(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
wire [3:0]abc;
assign abc=4'b1111;
initial begin
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
Cin=1'b1;
#10 //expecting 11
Multiplicand=1'b0;
Multiplier=abc[1];
Sin=1'b1;
Cin=1'b1;
#10 $stop;//expecting 10
end
endmodule
I can be wrong, but it seems there's a race condition between assigning value to abc and running initial block. At the moment when initial block started running, the assign abc =.. isn't executed yet. That's why you get x/red_lines in waveform view.
Verilog is an event driven simulator. It means that every 'always...', 'assign' block has inputs and outputs. Inputs in always block is are represented by its sensitivity list. In your case that would be the tmp signal. The whole block will start evaluation if and only if a change of an input is detected.
Also in the module the initial is scheduled for execution once during the simulation and is always executed first, before any of the always blocks (except in special cases in system verilog). So, in your case first few statements of the initial block (before first #10) are executed before the assign statement. So, for the first 10 cycles value of abc will be `4bxxxx, which explains your red line. For the same reason the values. As a result, values of multiplicand and consequently of MC/tmp,Sout,Cout will also be 'x'.
At #10 you change the values of the variables, causing always block in MC to re-evaluate with new values. By that time abc is already set to 1111 and all 'x' disappear.
So, efficiently you simulated only the second set of values but hot the first.
The suggestion is: add a small delay in front of the initial block:
initial begin
#1
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
This will delay execution of the statements and the value of 'abc' will be set by this time. You will have a short period (1) of the red line, but you will see results of the values you set.
Another possibility is to set value of abc in the initial block first, but you would need a reg variable to do so:
reg[3:0] abcSet;
assign abc = abcSet;
initial begin
abcSet = 4'b1111;
...
another thing, in your always block you use non-blocking assignment (<=). Do not! This is good for flops and latches but bad for simple combinatorial logic. Use the regular assignment there (=).
{Cout,Sout} = tmp+Sin+Cin;
Also, this always block will not be avaluated if you just change Sin or Cin and tmp stays the same. You should either add those into the sensitivity list:
always #(tmp, Sin, Cin)
or use always #* instead. Actually it is a good idea to always use this construct instead of regular V95 always blocks. This way you will avoid possible implicit latches in the design (as in your case in respect to missing parts of the sensitivity list).
Also, in general most of the modern designs are synchronous designs and use a clock signal for synchronization. In your case the multpliplier sell shoudl be synchronized as well, you would need to provide a toggling clock signal. In theis case your operation could look like the following:
always #(posedge clk)
{Cout,Sout} <= tmp+Sin+Cin;
It makes evaluation happen at positive edge of the clk signal, it it is the only member of the sensitivity list. All other signals should set before the clock change. And yes, it is a flop and <= is used there.

Always in a task?

I'm using Verilog for programming a FPGA.
I have my top module and I would like to call a Task which contains an always block.
The Task is a routine for serializing a byte in UART. (inputs: baudrate_clk, bytetosend ; output: TxD which is the physical output pin)
module serial();
task serial;
input baudrate;
input [7:0] data;
output TxD;
reg [3:0] state;
begin
always #(posedge baudrate) begin
case(state)
// ...
endcase
end
end
always #(state[2:0]) begin
case(state[2:0])
// ...
endcase
end
assign TxD ...
end
endtask
endmodule
I get a unexpected token: 'always' at the first always, always #(posedge baudrate) begin
I read Task could include wait, posedge etc...
If I cannot use Taks, what can I use for this purpose ?
Thank you.
Either your task should be a module or you should use a loop inside your task. It's difficult to see your design intent, but it looks to me that you needed a module in this case, not a task.
Tasks contain sequential code, just like an always block does. A task is just another place to put the kind of code that can go inside an always block. It makes no sense to put an always block inside a task.

Resources