Semaphore in system verilog - semaphore

module sema;
semaphore sem;
initial begin
sem=new(2);
begin
sem.get(1);
begin
$display("%t,Event 3", $time);
sem.put(1);
end
sem.get(2);
$display ("%t, Event1",$time);
sem.get(1);
begin
$display("%t,Event 2",$time);
sem.put(2);
end
end
end
endmodule
The outputs are supposed to be Event3, Event 2, Event1

Everything in your code is procedural, you need to fork the processes. The below will display Event3, Event2, Event1
initial begin
sem=new(2);
fork
begin
sem.get(1);
$display("%t, Event3", $time);
#1 sem.put(1);
end
begin
sem.get(2);
$display ("%t, Event1",$time);
#1 sem.put(2);
end
begin
sem.get(1);
$display("%t, Event2",$time);
#1 sem.put(1);
end
join
#1 $finish;
end

Related

Unable to understand error in D flip flop code

I have a problem in the test bench code, and I am not getting correct waveforms. Even the clock does not trigger.
CODE for D Flipflop:
module D_FF(o,D,clk);
output reg o;
input D,clk;
always # (posedge clk)
begin
if(D==1'b1)begin
o=1'b1;
end
else begin
o=1'b0;
end
end
endmodule
Code for TestBench:
module DD_flipflop_tb();
reg clk,D;
wire o;
D_FF i1(o,D,clk);
initial begin
clk=1'b0;
D=1'b0;
end
always begin
#20 clk=~clk;
#35 D=~D;
#5000 $finish;
end
endmodule
Here is what happens in the always block in your testbench.
At time 0, clk and D are 0.
At time 20, you invert clk, which becomes 1.
At time 55, you invert D, which becomes 1.
At time 5055, you call $finish which terminates the simulation. The statements in the block only execute once, which is why your inputs never change more than once.
In your testbench, initialize them as 0 in an initial block, then separate the clock generation from the data signal.
initial begin
clk = 0;
forever #20 clk=~clk;
end
initial begin
D=0;
forever #35 D=~D;
end
initial #5000 $finish;
You might want to assign separately the clock and the stimulus in the testbench:
initial begin
clk = 0;
D = 0;
#5000 $finish;
end
//..clock
always
#20 clk = ~clk;
//..stimulus
always
#35 D = ~D;

Verilog error :Assignment under multiple single edges is not supported for synthesis

When I want to make an elevator-like programme project, whatever I do to edit my module it always says:
Assignment under multiple single edges is not supported for synthesis
Some variables:
tar_floor : user input, target floor;
cur_floor : current floor located;
clk_cnt : variable added 1 each time to count.
always #(posedge clk or posedge clr) begin
if(clr)
begin
cur_floor = 0; //if clear button pressed,clear all statement
tar_floor=0;
upordown=0;
clk_cnt=0;
ryg=3'b001; //green
rgb=3'b111;
end
if(tar_floor==cur_floor) //nothing to do
begin
clk_cnt=0;
upordown=0;
clk_cnt=0;
ryg=3'b001; //green
rgb=3'b111;
end
else
begin//when up or down
clk_cnt = clk_cnt +1;
if (tar_floor>cur_floor)
begin
ryg=3'b100;//red
if (clk_cnt[27])
rgb=rgb+1;
if(clk_cnt[28])
begin
if (cur_floor<=6)
cur_floor=cur_floor+1;
end
end
if (tar_floor<cur_floor)
begin
ryg=3'b010;//yello
if (clk_cnt[27])
rgb=rgb+1;
if(clk_cnt[28])
begin
if (cur_floor>=1)
cur_floor=cur_floor-1;
end
end
end
end
wire tmp=cur_floor;
mytask_sub A1(.a_to_g(a_to_g),.cur_floor(tmp));//call show sub modudle
endmodule
At clk_cnt = clk_cnt +1;, it says:
Assignment under multiple single edges is not supported for synthesis
Please help me solve this error.
Synthesis requires you to structure your code like this:
always #(posedge clk or posedge clr)
if(clr)
// asynchronous statement when clr rises
// and any clk rising edge while clr is true
else
// synchronous statement when clk rises and clr is false
You are missing the else clause

Multiple begin end statement in verilog

Do different begin end statements executed concurrently in verilog?
Here's the code:
//Sample test values to run simulation (module jkflop_top continues)
initial begin
j=0; k=0; rst=1;
#4
j=1; k=1; rst=0;
#50
j=0; k=1; rst=0;
#20
j=1; k=1; rst=0;
end
//Carry out simulation for 100 units of time
initial begin
#100
$finish;
end
endmodule
What the code does is it provides sample input for a j-k flip flop. As the second begin should be finished after 100 units delay from starting of the program if they are concurrent, will the total program run for 100 time units only?
Different initial statements operate concurrently.This has nothing to do with begin/end.
The begin/end only 'group' all the code with one initial.
Here we have two begin/end statements. They do not operate concurrently, they operate sequentially.
for (i=0; i<8; i=i+1)
begin
... // some code
end
for (j=0; j<8; j=j+1)
begin
... // some more code
end
Here we have two initial statement, without begin/end. They operate concurrently.
initial
#50 reset = 1'b0;
initial
#100 clk= 1'b1;

mixing of blocking and nonblocking issue and first bit of the 16-bit input is not being considered

This is my complete code. input 'h' is a 16 data bits and a sign bit.Some particular patterns are to be recognized in these databits. So each databit is taken into a FSM and checked for that particular pattern.
Now ,There are two issues here:
The first issue is that first data bit is never taken into consideration.
And the second issue is that variable 'i' is assigned with both blocking and non-blocking(without which code doesn't seem to work). Can someone please help with this.
module formatting(x,h,sign,y0,y1,y2,y3,out1,out2,out3,out4,out5,
ft1,ft2,ft3,ft4,ft5,bit1,bit2,bit3,bit4,bit5);
input [16:0]x;
input [0:16]h;
output sign;
output [15:0]y0,y1,y2,y3;
output reg [1:0]out1,out2,out3,out4,out5;
output reg [3:0]ft1,ft2,ft3,ft4,ft5;
output reg bit1,bit2,bit3,bit4,bit5;
wire [15:0]x1;
reg inp;
integer i=0;
reg [2:0]s=3'b0;
reg [2:0]st=3'b0;
reg [3:0]ft=4'b0;
reg [2:0]cnt=3'b0;
reg [1:0]out;
assign sign=(x[0]^h[16]);
assign x1=x[16:1];
assign y0=((x1>>3)+(x1>>1)+(x1>>2));
assign y1=(x1>>1);
assign y2=((x1>>1)+(x1>>3));
assign y3=((x1>>2)+(x1>>1));
always#(i,h,inp)
begin
if(i<16)
begin
inp<=h[i+1];
i<=i+1;//non-blocking assignment of variable'i'
case(s)
3'b000:if(inp == 1'b1)
begin
if(i<=13)
begin
s=3'b001;
st=st+1'b1;
ft=i;
end
else if(i==14)
begin
s=3'b100;
st=st+1'b1;
ft=i;
end
else if(i==15)
begin
s=3'b000;
st=st+1'b1;
ft=i;
out=2'b01;
cnt=cnt+1'b1;
end
end
else
begin
s=3'b000;
end
3'b001: if(inp == 1'b0)
begin
s=3'b010;
end
else
begin
s=3'b011;
end
3'b010:if(inp == 1'b1)
begin
s=3'b000;
out=2'b10;
cnt=cnt+1'b1;
end
else
begin
s=3'b000;
out=2'b01;
cnt=cnt+1'b1;
end
3'b011:if(inp == 1'b1)
begin
s=3'b000;
out=2'b00;
cnt=cnt+1'b1;
end
else
begin
s=3'b000;
out=2'b11;
cnt=cnt+1'b1;
end
3'b100:if(inp == 1'b1)
begin
s=3'b000;
out=2'b11;
cnt=cnt+1'b1;
end
else
begin
s=3'b000;
out=2'b01;
cnt=cnt+1'b1;
end
default:begin
s=3'b000;
out=2'bxx;
end
endcase
case(cnt)
3'b001:begin
out1=out;
bit1=1'b1;
end
3'b010:begin
out2=out;
bit2=1'b1;
end
3'b011:begin
out3=out;
bit3=1'b1;
end
3'b100:begin
out4=out;
bit4=1'b1;
end
3'b101:begin
out5=out;
bit5=1'b1;
end
default:begin
out1=2'b00;bit1=1'b0;
out2=2'b00;bit2=1'b0;
out3=2'b00;bit3=1'b0;
out4=2'b00;bit4=1'b0;
out5=2'b00;bit5=1'b0;
end
endcase
case(st)
3'b001:begin
ft1=ft;
end
3'b010:begin
ft2=ft;
end
3'b011:begin
ft3=ft;
end
3'b100:begin
ft4=ft;
end
3'b101:begin
ft5=ft;
end
default:begin
ft1=4'b0000;
ft2=4'b0000;
ft3=4'b0000;
ft4=4'b0000;
ft5=4'b0000;
end
endcase
end
else
begin
i=0;//blocking assignment of variable'i'
st=3'b000;
cnt=3'b000;
ft=4'b0000;
s=3'b000;
end
end
endmodule
You are taking about an FSM. In HDL an FSM is a piece of code/hardware which trundles though a number of states using a clock. Your code does not have a clock and as such is not a FSM.
That also causes the confusion in your blocking and non-blocking assignments. In a clocked section you use only non-blocking assignments. In a combinatorial section you use only blocking assignments.
I am afraid you have to seriously re-write the code thinking of what needs to be done in each step (clock). Also add a reset signal. That will set an initial state from which everything starts.
Also nowadays the use of always (*) or always_comb is preferred. The danger is that you forget a variable in your sensitivity list and then your simulation will not match with the hardware.
Without clock you have to write the whole section using a single for loop:
for (i=0; i<16; i=i+1)
begin
// All logic expressed as a function of i
end
I foresee problems as you also have a case in there. HDL is as it says a Hardware Description Language. In the end you have a single piece of hardware which must do all the processing. Thus the synthesis tool must know all the hardware it must generate using compile time known values.

Verilog disable Statement not Working but $finish works but it is not synthesizable?

I want to design an counter which counts up to some number, lets say it is 3, for this I write a code that work well with "$finish" but not with "disable".
I want to use this counter for synthesis so I have to use "disable" statement .....
I have attached my both code-
(1) With $finish that stops easily & accurately
// Code with $finish
module counter(input wire clk);
reg [23:0]N=24'b0000_0000_0000_0000_0000_0000;
always # (posedge clk)
begin
if (N == 24'b0000_0000_0000_0000_0000_0011)
begin
$display("Inside If N=%d in Time=",N,$time);
$finish;
end
else
begin
N <= N +1;
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
(2) With disable that not stop at all..
// Code with disable that not stop
module counter(input wire clk);
reg [23:0]N=24'b0000_0000_0000_0000_0000_0000;
always # (posedge clk)
begin :close
if (N == 24'b0000_0000_0000_0000_0000_0011)
begin
$display("Inside If N=%d in Time=",N,$time);
disable close;
end
else
begin
N <= N +1;
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
toolic and Greg have both indicated to incorrect uses of $finish and disable, this is just to add to both of those points and show a possible solution, seperating test from synthesizable RTL.
module counter(input clk);
reg [23:0] N = 24'b0;
always # (posedge clk) begin
if (N < 24'd3) begin
N <= N +1;
$display("Inside If N=%d in Time=",N,$time);
end
else begin
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
To test it:
module test;
//Create clk
reg clk;
initial begin
clk = 0 ;
forever begin
#5 clk = ~clk;
end
end
//instantiate DUT (Device Under Test)
counter counter_i0(
.clk( clk )
);
// The test
// Run for 6 clock cycles then end
initial begin
repeat (6) begin
#(posedge clk)
end
$finish;
end
endmodule
If you mean to stop at count 3, I would use decimal notation 24'd3 for the constant, as it gives clear intent.
also if using == to stop a counter a glitch could cause this to be missed and you have to wait for this to wrap arround. Or using a less than comparator means that the count target can be adjusted on the fly with out fear of skipping the exact value in == and having to wait a really long time for it to wrap around.
inputs are implicitly wires, no need to define them as such but you can if you want.
Put the $finish at the end of your test bench, not in your synthetically RTL.
$finish stops all running processes and ends the simulation. disable stops one process and its child processes. In your sample code, disable close terminates the code within the always block, it does not stop the clock. The next positive edge clock and the always block will try to run again.
See IEEE std 1800-2012 § 20.2 for the $finish statement and § 9.6.2 for the Disable statement

Resources