Implementation of wait statement inside a fork join block - system-verilog

what modification is needed to display i value =5,2,7? I am not getting output. Any suggestion will be helpful.
module tb#(int T=8);
bit [8:0] abc;
initial
begin
for(int i=0; i<T; i++)
begin
fork
begin
wait(abc[i] == 1'b1);
$display(i,$time);
end
join_none
end
end
initial
begin
abc[5] = 1'b1;
#10 abc[2] = 1'b1;
abc[7] = 1'b1;
end
endmodule
https://www.edaplayground.com/x/JUZR

There is only one instance of the variable i and it's value is 8 by the point in time that the process begins. You need to declare a variable k that has a different value for each iteration of the loop.
module tb#(int T=8);
bit [8:0] abc;
initial
begin
for(int i=0; i<T; i++)
begin
automatic int k = i;
fork
begin
wait(abc[k] == 1'b1);
$display(i,k,,,$time);
end
join_none
end
end
initial
begin
abc[5] = 1'b1;
#10 abc[2] = 1'b1;
abc[7] = 1'b1;
end
endmodule
See https://verificationacademy.com/forums/systemverilog/fork-joinnone-inside-loop

Related

How to pass a reference array of variables to task?

I am trying to pass a reference array of variables. It works fine with a reference to variable, but not with an array of variables. The goal with the task is to be able to take an array of variables, and read them on every clock edge.
So this code does not work
module tb;
logic clock = 0;
logic a = 0;
logic b = 0;
task automatic read_vars(ref logic clock, input int clock_edges = 10,
const ref logic signal_array[]);
repeat (clock_edges) begin
#(posedge clock) $display("#TIME: %t Clock edge", $time);
for (int i = 0; i < signal_array.size(); i++) begin
$display("Variable %0d: %0b", i, signal_array[i]);
end
end
endtask
always begin
#1 clock = 1;
#1 clock = 0;
end
always begin
#3 b = 1;
#3 b = 0;
end
always begin
#7 a = 1;
#7 a = 0;
end
initial begin
fork
read_vars(.clock(clock), .signal_array({a, b}));
join_none
#1000;
$finish();
end
endmodule
I get the following error
read_vars(.clock(clock), .signal_array({a, b}));
|
xmvlog: *E,BADRFA (tb.sv,25|45): invalid ref argument usage because actual argument is not a variable. [SystemVerilog].
module worklib.tb:sv
But this code works.
module tb;
logic clock = 0;
logic a = 0;
logic b = 0;
task automatic read_vars(ref logic clock, ref logic a, ref logic b, input int clock_edges = 10);
repeat (clock_edges) begin
#(posedge clock) begin
$display("#TIME: %t Clock edge", $time);
$display("a = %b ", a);
$display("b = %b ", b);
end
end
endtask
always begin
#1 clock = 1;
#1 clock = 0;
end
always begin
#3 b = 1;
#3 b = 0;
end
always begin
#7 a = 1;
#7 a = 0;
end
initial begin
fork
read_vars(.clock(clock), .a(a), .b(b));
join_none
#1000;
$finish();
end
endmodule
What you are trying to do is impossible in verilog.
First of all, having a reference to an array will not help in solving the issue. Arrays contain values of something. So creation of an array with {a,b} will just copy values of the variables into the array and updating variables will not be reflected in any case.
What you are after is an array of references to variables, which is impossible in a verilog.
However, class variables are always reference. So, you can wrap your vars in a class in test bench. Here is a modified example of yours:
class V;
logic val;
endclass:V
module tb;
V a = new;
V b = new;
V arr[] = '{a, b};
logic clock = 0;
//logic a = 0;
//logic b = 0;
task automatic read_vars(ref logic clock, input int clock_edges = 10,
V signal_array[]);
repeat (clock_edges) begin
#(posedge clock) $display("#TIME: %t Clock edge", $time);
for (int i = 0; i < signal_array.size(); i++) begin
$display("Variable %0d: %0b", i, signal_array[i].val);
end
end
endtask
always begin
#1 clock = 1;
#1 clock = 0;
end
always begin
#3 b.val = 1;
#3 b.val = 0;
end
always begin
#7 a.val = 1;
#7 a.val = 0;
end
initial begin
fork
read_vars(.clock(clock), .signal_array(arr));
join_none
#1000;
$finish();
end
endmodule

system verilog: for loop index variable issue

`timescale 1ns / 1ps
module param_right_shifter
# (parameter N = 3)
(
input logic [$clog2(N)-1:0] a, // input
input logic [N-1:0] amt, // shift bits
output logic [$clog2(N)-1:0] y // output
);
logic [$clog2(N)-1:0][N:0] s;
logic [$clog2(N)-1:0] placeholder = a;
localparam bit_num = $clog2(N)-1;
always_comb
begin
for(int i = 0; i < N; i++)
begin
if (i == 0)
begin
s[i] = amt[i] ? {placeholder[i], placeholder[bit_num:2**i]} : placeholder;
placeholder = s[i];
end
else
begin
s[i] = amt[i] ? {placeholder[$clog2(N)-1:0], placeholder[bit_num:2**i]} : placeholder;
placeholder = s[i];
end
end
end
endmodule
I am having an issue with referencing the 'i' variable. It says that 'range must be bounded by constant expressions'. I am unsure of how to resolve.
Try below. I am assuming N is will have a constant value throughout the simulation.
Please note that placeholder is driven by all bits of s so here placeholder will settle to s[N-1].
genvar i;
generate
for(i = 0; i < N; i++)
begin
if (i == 0)
begin
always_comb
begin
s[i] = amt[i] ? {placeholder[i], placeholder[bit_num:2**i]} : placeholder;
placeholder = s[i];
end
end
else
begin
always_comb
begin
s[i] = amt[i] ? {placeholder[$clog2(N)-1:0], placeholder[bit_num:2**i]} : placeholder;
placeholder = s[i];
end
end
end
endgenerate

"Illegal reference to net " error in systemverilog - trying to design simple arbitrer

Here is the code I have for simple arbitrer
module arbiter(clk,rst,req,grnt,req_val);
input clk;
input rst;
input [3:0] req;
input [3:0] req_val;
output [3:0] grnt;
int j;
int i;
parameter A = 2'd0;
parameter B = 2'd1;
parameter C = 2'd2;
parameter D = 2'd3;
logic [1:0] current_state;
logic [1:0] next_state;
always_comb
begin
case (current_state)
D:
begin
grnt = 4'b1000;
j = 0;
for (i = 0; i<4;i++) begin
if (req[(j+i) % 4 ] == 1)
break;
end
case (i)
0: next_state = A;
1: next_state = B;
2: next_state = C;
3: next_state = D;
endcase
end
A:
begin
j = 1;
grnt = 4'b001;
for (i = 0; i<4;i++) begin
if (req[(i+j) % 4] == 1)
break;
end
case (i)
0: next_state = A;
1: next_state = B;
2: next_state = C;
3: next_state = D;
endcase
end
B:
begin
j = 2;
grnt = 4'b0010;
for (i = 0; i<4;i++ ) begin
if (req[(i+j) % 4] == 1)
break;
end
case (i)
0: next_state = A;
1: next_state = B;
2: next_state = C;
3: next_state = D;
endcase
end
C:
begin
j = 3;
grnt = 4'b0100;
for (i = 0; i<4;i++ ) begin
if (req[(i+j)% 4] == 1)
break;
end
case (i)
0: next_state = A;
1: next_state = B;
2: next_state = C;
3: next_state = D;
endcase
end
endcase
end
endmodule
always_ff#(posedge clk)
begin
current_state <= next_state;
end
endmodule
and I get the following error:
arbitrer.sv(21): (vlog-2110) Illegal reference to net "grnt".
and
arbitrer.sv(87): near "always_ff": syntax error, unexpected always_ff, expecting class.
So whats wrong with grnt ? I cant assign directly to a module output ?
There are two problems with your code.
You have used endmodule statement twice in your code. Just comment out one at line number 86.
You haven't define a data type for grnt variable, so by default it's a wire and wire can't be used in always block, so declare it as a reg/logic.

2 Bit Counter using JK Flip Flop in Verilog

I'm writing verilog code of 2 Bit Counter using JK Flip Flop that counts 0-3 and back to 0. I'm using Xilinx EDA. However I'm keep getting one error and I don't know what it means? The line numbers doesn't show up here, but error is located at "always #(posedge clk)".
ERROR:HDLCompiler:1401 - "C:\Users\Eduardo\Documents\SFSU\Fall 2014\Engr 378\Lab 3\TwoBitCounter\twobitcounter.v" Line 30: Signal q in unit jkff is connected to following multiple drivers:
`timescale 1ns / 1ps
module twobitcounter( q_out, qbar_out, j,k, clk, reset);
input [1:0] j; input [1:0] k; input clk; input reset;
output [1:0] q_out;
output [1:0] qbar_out;
wire [1:0] q_out;
wire [1:0] qbar_out;
wire clk;
assign qbar_out[0] = ~q_out[0];
assign j[0] = 1;
assign k[0] = 1;
assign j[1] = q_out[0];
assign k[1] = q_out[0];
jkff M1(q_out[0], qbar_out[0], j[0], k[0], clk, reset);
jkff M2(q_out[1], qbar_out[1], j[1], k[1], qbar_out[0]);
endmodule
module jkff(output q_out, output qbar_out,
input j, input k, input clk, input reset);
reg q;
assign q_out = q;
assign qbar_out = ~q;
initial begin
q = 1'b0;
end
always #(posedge clk)
begin
case({j,k})
{1'b0, 1'b0}: begin
q = q;
end
{1'b0, 1'b1}: begin
q = 1'b0;
end
{1'b1, 1'b0}: begin
q = 1'b1;
end
{1'b1, 1'b1}: begin
q = ~q;
end
endcase
end
always #(posedge reset)
begin
q = 1'b0;
end
endmodule
The issue is q is being set in two always blocks, which is not allowed in synthesis. Merge the two always blocks. Also, q is a flop, so it should be assigned using non-blocking assignment (<=), not blocking assignment (=).
always #(posedge clk or posedge reset)
begin
if (reset == 1'b1) begin
q <= 1'b0;
end
else begin
case({j,k})
{1'b0, 1'b0}: begin
q <= q;
end
{1'b0, 1'b1}: begin
q <= 1'b0;
end
{1'b1, 1'b0}: begin
q <= 1'b1;
end
{1'b1, 1'b1}: begin
q <= ~q;
end
endcase
end
end
You should almost never use initial blocks in synthesizable code. Most FPGAs allow it for initialization. ASICs designs however do not support it. For both cases, if there is an asynchronous reset/set then it initial block shouldn't be used.
The error is telling you that you are assigning q in different blocks. This creates an error. You are assigning q in both your initial block and your always block.
You should never use initial blocks in synthesizable code.

DRDY signal in Verilog

in my recent CPLD design I implemented a frequency counter with an SPI slave interface. The SPI master MCU reads out the counter after it is signalled by a DRDY pin. My counter updates the DRDY signal by flipping it (DRDY <=~DRDY) but it requires both edges pin interrupt sensitivity at the MCU side. I'd like to implement it more universally, like the typical ADC chip data ready signal behaviour, which is: a rising edge, held for x clocks then a falling edge. I thought it should be easy however I stucked in conditional loops as a beginner in Verilog.
Here is my code so far:
module ec2(INP, RST, SR, DRDY, DRDY2, DRDY3);
input INP, RST, SR;
output reg DRDY2, DRDY3;//LEDs for verification/testing purposes
output reg DRDY;
reg [23:0] Q;
event data_ready;
always #(posedge INP or negedge RST)
begin
if(!RST)
begin
Q <= 24'd0;
end
else if( (Q == 24'd1000000 && SR) || (Q == 24'd500000 && !SR))
begin
Q <= 24'd0;
->data_ready;
DRDY2 <=~DRDY2;
end
else
begin
Q <= Q + 1;
end
end
always #(data_ready)
begin
DRDY=1'b1;
//wait for 10ms?
DRDY=1'b0;
DRDY3 = DRDY2;
end
endmodule
Events are not synthesizable, you should convert data_ready into a signal (reg). A second counter which triggers DRDY at data_ready assertion would do the trick:
always #(posedge INP or negedge RST)
begin
if (RST)
begin
DRDY <= 1'b0;
drdy_count <= 4'd0;
end
else
begin
if (~DRDY && data_ready)
begin
DRDY <= 1'b1;
drdy_count <= 4'd0;
end
else if (DRDY)
begin
drdy_count <= drdy_count + 1;
if (drdy_count == 15)
DRDY <= 1'b0;
end
end
end