How to give input to a task - verilog

I've created a task in my testbench which takes 3 inputs, but it seems that the value of one of them is wrong.
Below there is my code. I already know that s has the same value of dut.r.f, but when I run the simulation it's not like this.
MAIN:
module main(
input logic clk,
input logic vaux2_p,
input logic vaux2_n,
output logic gpio1,
);
logic [8:0] f;
inst r(
.clk (clk),
.f (f),
);
endmodule
R:
module inst(
input logic clk,
output logic [ 8:0] f
);
always_ff #(posedge clk) begin
f <= 8'h0_F0;
end
endmodule
TESTBENCH:
module m();
logic clk;
logic vaux2_p;
logic vaux2_n;
logic gpio1;
main dut(
.clk(clk),
.vaux12_p (vaux2_p),
.vaux12_n (vaux2_n),
.gpio1 (gpio1)
);
task test;
input [ 7:0] a;
input [8:0] v;
input [8:0] s;
integer f1;
begin
f1 = $fopen("file.txt","w");
if (!f1) begin
$display("File \"file.txt\" cannot be opened!");
end else begin
//this part of code is just for test what I'm reading
$fdisplay(f1," f: %0h %0b %0d", dut.r.f,dut.r.f,dut.r.f);
$fdisplay(f1,"s: %0h %0b %0d", s,s,s);
$fdisplay(f1,"v: %0h %0b %0d", v,v,v);
$fclose(f1);
end
endtask
initial begin
test(8'h19,24'hFF00, dut.r.f);
$finish;
end
endmodule
If I run this code and then I open the file.txt what I can read is this:
f: f0 11110000 240
s: xxxxxx xxxxxxxxxxxxxxxxxxxxxxxx x
v: f0 11110000 240
I was thinking that this can be due to the fact that at the beginning of the simulation dut.r.f=xxxxxx and only after few ns it turns in f0, but then I realized that this cannot be the problem for two reasons: the first one is that if the value of the signals is taken at the beginning of the simulation, also f should be equal to xxxxxx, the second one is that even if I introduce a delay before I display the signal values, the problem still exists.
Do you know if there is any issue in passing a variable from main as input for the task? If yes, it's the same also with functions?
Can anyone kindly help me, please? Thanks!

The problem here is task input arguments get passed by value only when entering the task test. Further updates to the actual arguments to not get passed through. You need to use pass by reference to see later updates.. Change you task declaration to
task test(
input logic [ 7:0] a,
input logic [8:0] v,
ref logic [8:0] s);
int f1;
See this post for more details.

Assuming your provided test bench is complete, the fundamental problem is the clock that dut.r.f is dependent on never toggles.
initial begin
clk = 1'b0; // init clock;
#1; // time to propagate
clk = 1'b1; // will trigger #(posedge clk) if connected properly
#1; // time to propagate
test(8'h19,24'hFF00, dut.r.f);
$finish;
end
If you want to start the task before toggling the clock, you will need to use SystemVerilog's ref instead of input as mentioned in dave_59's answer, and add time delay.

Related

How to properly pass data to a submodule and get results back in verilog?

Say I have a submodule and want to "call" it from a top module.
//sub.v
module sub(
input wire clk,
input wire rst_n,
input wire update,//interface is modifiable
input wire [7:0] in_data,
output wire[7:0] out_data
);
reg[7:0] state;
always #(posedge clk) begin
if(!rst_n)
state<=0;
else if(update)
state<=state+in_data;//update drives states to change according to input data
end
assign out_data=state<<1;
endmodule
//top.v
module top(
input wire clk,
input wire rst_n,
output reg[7:0] top_out
);
//Submodule
reg sub_update;
reg[7:0] sub_in;
wire[7:0] sub_out;
sub sub_instance(
.clk(clk),
.rst_n(rst_n),
.update(sub_update),
.in_data(sub_in),
.out_data(sub_out)
);
//Topmodule
reg[7:0] top_state;
localparam STATE0 = 8'd0;
localparam STATE1 = 8'd1;
localparam STATE2 = 8'd2;
localparam STATE3 = 8'd3;
localparam TEMP_STATE = -8'd1;
always #(posedge clk) begin
if(!rst_n) begin
top_state <= STATE0;
sub_update <= 0;
sub_in <= 0;
end else begin
case (top_state)
STATE0:top_state<=STATE1;
STATE1:begin
//want to update the submodule and use its output here
sub_in <= 123;
sub_update <= 1;
top_state <= TEMP_STATE;
end
STATE2:top_state<=STATE3;//proceed from STATE1
TEMP_STATE:begin
sub_update <= 0;
top_out <= sub_out+1;
top_state <= STATE2;
end
default:top_state<=STATE0;
endcase
end
end
endmodule
The main question may divide into 2 smaller questions:
In my module code, the "update" signal is both set and captured at the same edge of a same clock. Is that a data race? Should I use a different edge, or pass a reverse clock to the submodule? Or should I change "update" to other interface?
Is there a better way to get the submodule output than using a temporary state? For this simple example, there is a way to calculate the output when the input is ready: Inline everything, get top_out<=((state+123)<<1)+1; at STATE1. Can this be generalized for more complicated calculation?
there is no problem in setting and capturing 'update' on the same clock edge. Just note that it will be captured with a delay of one clock cycle after it is set. This is the way flops work and your simulation should work same way because you did correctly use NBAs.
This is the question that you should answer for yourself. Better ways or not depend on your requirements and abilities of hardware. You have all these parts of the equation and states for some reason. You can probably collapse them if your algorithm allows it. You can use complex calculations there if they do not violate your design rules.

How to assign initial value to an input reg: Design compiler delete the assignment

I'm newbie in ASIC design. I have a design with for example two inputs a ,b. I'm using the following code for initialize these two signals. But the Design compiler generating a warning that the register "a" is a constant and will be removed. When I'm trying to do post-synthesis simulation these two signals are all 'z'. So how can I apply initial signal assignment to avoid such a problem?
always #(posedge(clk) or posedge (rst)) begin
if (rst) begin
a<=4d'5;
b <=4'd10;
end
end
While describing hardware system, you need to consider that input signals to your module comes from another module/system and their values are decided by that signals. Inputs to any module can only be wire type.
You can think of a module as a box that has inputs and outputs. The values of output signals are decided by input signal + logic inside the box. However, the module cannot decide what its inputs should be. It is only possible if there is feedback, and even in that case it would depend on other signals that are outside of the module's control.
As a result, output signals can be declared as output reg but the same is not true for inputs. However there is solution to your problem, I think what you want can be designed using the following method:
module your_module(
input clk,
input rst,
//other inputs and outputs that you might need
input [3:0] a,
input [3:0] b
);
//define registers
reg [3:0] a_register;
reg [3:0] b_register;
/*
These registers are defined to make it possible to
to give any value to that logics when posedge rst
is detected, otherwise you can use them as your
input logics
*/
//use initial block if you need
always#(posedge clk or posedge rst) begin
if(rst) begin
a_register <= 4'd5;
b_register <= 4'd10;
end
else
begin
a_register <= a;
b_register <= b;
// and use a_register and b_register as you want to use a and b
end
end
endmodule

Asynchronous reset D flipflop code syntax error

I'm writing a code to implement an asynchronous reset D flipfip, but the always# line is showing a syntax error:
`timescale 1ns / 1ps
module Dflipflop(
input D,
input reset,
input clk,
output Q
);
reg Q;
initial
begin
if(reset==1) //clear the output (Q=0)
begin
Q <= 0;
end
else if(reset==0)
begin
always#(posedge clk) //syntax error here...
begin
Q <= D;
end
end
end
endmodule
What could be the possible error, and is there a better logic for implementing the same ?
First of all I would not encourage you to use the initial statement except in testbench. This is not synthetizable so it should not appear in RTL.
Then I think you are confusing Verilog with a standard programming language which it is not.
In Verilog, there is two classes of statements:
processes, like always or initial
assignment, with assign that allows you to directly assign a 'value' to a wire
In processes there can be distinguished two classes :
Synchronous processes, //do something statements begin end will be evaluated only when an edge, specified in the #, occurs
always # (posedge clock) begin
//do something
end
Combinatorial processes, //do something statements will be evaluated every time the value of a wire or reg used in the //do something block changes
always #* begin
//do something
end
Here you have instantiated a process inside a process something that has no physical reality.
Another point, as described you want to activate the process only when reset==0 so you put a condition to enter the process. Once more, that does not make any sense in terms of synthesis. The process should be activated and that is in the process that the conditions should be evaluated.
A classical solution for implementing a D flip-flop with asynchronous reset is the following:
module Dflipflop(
input D,
input reset,
input clk,
output reg Q
);
always # (posedge clk or negedge reset) begin
if (!reset)
Q <= 1'b0; // Clear Q when reset negative edge occurs
else
Q <= D; // Capture D in Q when clk positive edge occurs and reset is high
end
endmodule
You cannot have always block inside initial. It should be written like this:
`timescale 1ns / 1ps
module Dflipflop(
input D,
input reset,
input clk,
output Q
);
reg Q;
always #(posedge clk, posedge reset)
begin
if(reset==1) //clear the output (Q=0)
begin
Q <= 0;
end
else
begin
Q <= D;
end
end
endmodule
You should either use initial(not recommended for synthesis) or always. One procedural block cannot come inside another. If you are really interested in designing a non-synthesizable logic and want to try out with initial, you can do something like this mentioned below. Both initial and always are procedural blocks.
....
else if(reset==0)
begin
repeat(100000) #(posedge clk)
begin
Q <= D;
end
end
end

Input Output for 8-bit ALU using FPGA board

I am a newbie to xilinx so please excuse any stupidities in the code.
Ah so I am trying to design an 8-bit ALU and the module is working perfectly on the simulation but we need to take inputs and display outputs on FPGA board.
Technically I should have used RS-232 but since we just have an 8-bit input and 8 switches are available, we are trying to code it this way.
However, the code does not compile and gives error
"expecting 'endmodule', found 'forever'".
I used 'forever' and not 'always' because always does not allow any instance to be instantiated within it.
Can anybody please help us figure out what is wrong with the code?
module main(out,in,switch);
output [7:0] out;
input [7:0] in;
input switch;
reg [7:0] a,b,select;
reg [1:0] count;
wire eq, comp, C8;
initial
begin
count = 2'b00;
select = 8'b0000_0000;
end
MyALU A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
forever
begin
if (switch)
begin
case (count)
00:
begin
a = in;
count = 2'b01;
end
01:
begin
b = in;
count = 2'b10;
end
10:
begin
select = in;
A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
count = 2'b00;
end
default
a = in;
endcase
end
end
Every module in verilog must end with the line endmodule. That is missing in your code. And try using always#(*) instead of forever. forever is not synthesizable and only used for verification with simulation.
Replace the forever statement by always #(*).
Remove this line from the case statement:
A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
Add endmodule at the end.

Parameterized number of cycle delays in verilog?

I have to delay a few control signals in a pipeline I've designed by the number of stages in the pipeline. This is obviously very straight forward -- just put N flip-flops in between the the input signal and output signal. I'm wondering if there's a way to parameterize N. If I ever change the number of stages in the pipeline I have to go back and add/remove flip-flops, which is sort of annoying. I thought about just writing a script to read a define somewhere and generate the module, but that seems like overkill. Is a genvar loop the right way to go here?
You could use a parameterized shift register to do this. Something like:
module shift
(
input clk,
input data_in,
output data_out
);
parameter DEPTH = 3;
reg [DEPTH-1:0] holding_register;
always # (posedge clk) begin
holding_register <= {holding_register[DEPTH-2:0], data_in};
end
assign data_out = holding_register[DEPTH-1];
endmodule
Another alternative would be to use a generate statement to create essentially the same effect.
Here is how to created the parameterized shift register using a generate block and a DFF module. It even works with DEPTH=0 and DEPTH=1.
module shift
(
input clk,
input reset,
input data_in,
output data_out
);
parameter DEPTH = 3;
wire [DEPTH:0] connect_wire;
assign data_out = connect_wire[DEPTH];
assign connect_wire[0] = data_in;
genvar i;
generate
for (i=1; i <= DEPTH; i=i+1) begin
dff DFF(clk, reset,
connect_wire[i-1], connect_wire[i]);
end
endgenerate
endmodule
Complete working code with a test on EDA Playground: http://www.edaplayground.com/s/4/50

Resources