The term “asynchronous” can refer to several different scenarios. Here is a brief description of some more common scenarios that we will study:
Asynchronous handshaking is an important technique for coordinating processes that have variable timing. To illustrate this concept, consider a competitive foot race with three states:
To coordinate this race, the officials use three
flags for signaling: ready, start, and done. Before the competitors
can line up, all three flags must be LOW. Once the runners are in
position, the ready flag can go
HIGH.
When the race official sees the ready flag, the start flag may go HIGH to start the
race. Meanwhile, down at the finish line, once the start flag goes HIGH a race observer
watches the runners to verify when they have all completed the race. At
the end, the done flag goes
HIGH.
At any time after raising the start flag, the ready flag can by lowered since the
runners are no longer in the ready position. Once the done flag goes HIGH, the start flag may be lowered since the
race is over. After the start
flag is lowered, the done flag
can go LOW again. Once all three flags are LOW, another set of runners
can queue up at the starting line to begin another race.
The timing of this handshaking dance is shown in the figure below. Two race events are shown. The run time is indicated for each race, as well as the delay between races. Both the run time and delay can vary from one race to the next. Since the schedule is not absolute and repeatable, we need to use handshaking with the flags.
A state transition diagram for the handshaking protocol is shown
below. This state diagram responds to two inputs: ready and done. It controls one output: start. Elsewhere in the design, there
must be other state machines that control the ready and done signals.
In digital systems, the “runners” represent data. The “race”
represents some process that uses the data, where the process may take
an unknown number of clock cycles to complete. We model this system
using two modules: the race_official and the race_observer. The race_official is implemented as
follows:
module race_official
(
input clk,
input rst_l,
input ready,
input done,
output reg start
);
reg [1:0] state;
always @(posedge clk, negedge rst) begin
// ACTIVE-LOW RESET:
if (!rst_l) begin
state <= 0;
start <= 0;
end
// NORMAL (NON-RESET) BEHAVIOR:
else begin
case (state)
0: begin
if (ready) begin
start <= 1;
state <= 1;
end
else
start <= 0;
end
1: begin
if (done) begin
start <= 0;
state <= 2;
end
end
2: begin
if (!done && !ready)
state <= 0;
end
default:
begin
start <= 0;
state <= 0;
end
endcase
end
end
endmoduleSome important features of this model:
state signal is two bits
wide, since there are three states. In Verilog, it’s crucial to declare
an adequate number of bits for state variables. One of the most common
design errors is to declare too few bits; if our state variable had only one bit, it
would never reach state 2.case statement
has a default
condition. This is necessary since a hardware state machine could find
itself in an erroneous state (e.g. state 3) due to some electrical
error. If that happens, it needs a way to recover from the fault.race_observer moduleDesign a state machine and Verilog module for the race_observer, according to these
specifications:
clk, rst_l, startdone!rst_l, done goes LOW!start, done goes LOWstart, done goes HIGH after a random
delay.random_timer submoduleTo simulate a random delay, use this
non-synthesizeable random_timer submodule:
module random_timer
(
input clk,
output reg t
);
reg [1:0] r; // random number
always @(posedge clk) begin
r <= $random();
if (r == 0)
t <= 1;
else
t <= 0;
end
endmoduleIn your race_observer module,
place an instance of random_timer and connect it to a wire named
t:
wire t;
random_timer rt1 (.clk(clk), .t(t));Create a state transition diagram for race_observer. The diagram’s
conditions should involve start, rst_l and t. The diagram’s
assignments should act on done. Use the t signal as a condition for all
transitions, e.g. done can only
go high when t==1.
Scan or save the diagram in a graphical format in this assignment
directory, with filename diagram.png or diagram.jpg or whatever graphics type
you prefer to use. Implement the diagram’s state-transition logic in a
file named src/race_observer.v.
Once your race_observer is
complete, type make simulate to
simulate the official/observer handshaking. One handshaking event should
look something like the example shown below, progressing from all-zeros
to ready, then start, then done, then back to
zeros.
clk: 5 ready: 0 start: 0 done: 0 start_state: 0 done_state: 0
clk: 6 ready: 0 start: 0 done: 0 start_state: 0 done_state: 0
clk: 7 ready: 0 start: 0 done: 0 start_state: 0 done_state: 0
clk: 8 ready: 0 start: 0 done: 0 start_state: 0 done_state: 0
clk: 9 ready: 1 start: 0 done: 0 start_state: 0 done_state: 0
clk: 10 ready: 1 start: 1 done: 0 start_state: 1 done_state: 0
clk: 11 ready: 0 start: 1 done: 0 start_state: 1 done_state: 1
clk: 12 ready: 0 start: 1 done: 0 start_state: 1 done_state: 1
clk: 13 ready: 0 start: 1 done: 0 start_state: 1 done_state: 1
clk: 14 ready: 0 start: 1 done: 0 start_state: 1 done_state: 1
clk: 15 ready: 0 start: 1 done: 1 start_state: 1 done_state: 2
clk: 16 ready: 0 start: 0 done: 1 start_state: 2 done_state: 2
clk: 17 ready: 0 start: 0 done: 0 start_state: 2 done_state: 0
clk: 18 ready: 0 start: 0 done: 0 start_state: 0 done_state: 0
clk: 19 ready: 1 start: 0 done: 0 start_state: 0 done_state: 0
Study the output to verify that the handshaking process is correct,
you should note several races are completed, with each race taking
different times to complete. Examine the ready signal and note the minimum and
maximum delays between races. Similarly, examine the done signal and measure the minimum
and maximum running time.
Turn in your work using git:
git add diagram* src/*.v *.txt
git commit . -m "Complete"
git push origin mainIndicate on Canvas that your assignment is done.