//----------------------------------------------------------------------
// Copyright 2020 Mentor Graphics Corporation
//
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------------------
//
//
// --------------------------------------------------------------
// Welcome to Mentor's Systemverilog Race Condition Challenge!!
// --------------------------------------------------------------
//
// Instructions:
//
// For each of the 10 race conditions below:
// * identify the race
// * re-code to remove the race
//
// Check your answers at: blogs.mentor.com/verificationhorizons
//
// NOTE: this is a Systemverilog static analysis exercise. You don't
// *need* to run the code to complete it (in fact it's better
// if you don't run it!) But if you do want to run it, you'll
// need a validated account to access Questasim.
//
//----------------------------------------------------------------------
module Mentor_race_condition_challenge (
output byte basket,
output logic ping,
output byte football,
output byte beach_ball,
output bit throw,
output byte baseball,
output byte hockey,
output bit[3:0] cricket,
output byte muscles
);
bit clk;
initial forever clk = #5 ~clk;
//---------------------------------------
// Race #1
//
// Blocking and non-blocking assignments
//---------------------------------------
byte slam;
bit dunk;
initial begin
forever begin
@(posedge clk);
dunk = ~dunk;
slam += dunk;
end
end
always @(posedge clk) basket <= slam + dunk;
//-------------------------------
// Race #2
//
// Unknowns at initialization
//-------------------------------
logic pong;
initial begin
fork
forever begin
@(posedge clk);
if (pong) ping = 0;
else ping = 1;
end
forever begin
@(posedge clk);
if (ping) pong = 0;
else pong = 1;
end
join_none
end
//---------------------------------------
// Race #3
//
// Procedural and continuous assignments
//---------------------------------------
byte colours, stripes, bouncy;
always @(posedge clk) stripes += 1;
always begin
@(posedge clk);
colours += 1;
beach_ball = bouncy;
end
assign bouncy = colours && stripes;
//-------------------------------
// Race #4
//
// Incomplete sensitivity list
//-------------------------------
bit score;
byte fieldgoal, touchdown;
byte down;
always @(posedge clk) begin
if (down < 4) begin
score <= 1;
fieldgoal <= fieldgoal + 3;
touchdown <= touchdown + 7;
down <= down + 1;
end
else begin
score <= 0;
down <= 0;
end
end
always @(score) football = fieldgoal + touchdown;
//------------------------------------
// Race #5
//
// fork/join* that don't consume time
//------------------------------------
bit shot_put;
bit javelin;
initial begin
@(posedge clk);
fork
shot_put = $random();
javelin = $random();
join_none
@(shot_put or javelin)
throw = (shot_put || javelin);
end
//-----------------------------------
// Race #6
//
// assignments in more than 1 thread
//-----------------------------------
bit single, double, triple, homerun, cycle;
initial begin
forever begin
@(posedge clk);
single = $urandom_range(0,10) > 1;
double = $urandom_range(0,10) > 2;
triple = $urandom_range(0,10) > 4;
homerun = $urandom_range(0,10) > 8;
end
end
initial begin
forever begin
#1 cycle = & { single, double, triple, homerun };
@(posedge clk);
end
end
always @(posedge clk) begin
#1 baseball = baseball + homerun;
if (cycle) begin
#0 cycle = 0;
end
end
//-------------------------------
// Race #7
//
// Edge sensitive events
//-------------------------------
bit [3:0] goal;
always @(posedge clk) goal += 2;
initial begin
@(posedge clk);
@(goal == 2) hockey = 1;
end
//-------------------------------
// Race #8
//
// Named events
//-------------------------------
event wicket, batsman;
initial begin
@(posedge clk);
fork
forever begin
@batsman;
repeat (cricket+1) @(posedge clk);
->wicket;
end
forever begin
->batsman;
@wicket;
cricket += 1;
end
join_none
end
//-------------------------------
// Race #9
//
// NBA functions
//-------------------------------
bit [3:0] bump, spike, side_out;
function bit [3:0] set(bit [3:0] _bump);
set <= _bump ^ (_bump << 1);
endfunction
initial begin
forever begin
@(posedge clk);
bump += 1;
spike = set(bump);
side_out = bump < spike ? spike : 0;
end
end
//-------------------------------
// Race #10
//
// Procedural force/release
//-------------------------------
byte pushups, situps, reps;
assign situps = 3 + pushups;
always @(posedge clk) reps <= reps + 1;
always begin
@(posedge clk);
pushups += reps;
force situps = 0;
@(posedge clk);
release situps;
muscles = pushups + situps;
end
initial #300 $finish();
endmodule