0% found this document useful (0 votes)
15 views11 pages

Lab 4

The document describes a music player system with 4 main modules: a master control unit (MCU), song reader, note player, and codec conditioner. The MCU controls playback state in response to buttons and tells the song reader which song to play. The song reader retrieves notes from a song ROM and passes them to the note player. The note player generates audio samples for each note and passes them to the codec conditioner. The conditioner outputs samples to match the audio chip's timing and drives playback.

Uploaded by

My Phone You
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views11 pages

Lab 4

The document describes a music player system with 4 main modules: a master control unit (MCU), song reader, note player, and codec conditioner. The MCU controls playback state in response to buttons and tells the song reader which song to play. The song reader retrieves notes from a song ROM and passes them to the note player. The note player generates audio samples for each note and passes them to the codec conditioner. The conditioner outputs samples to match the audio chip's timing and drives playback.

Uploaded by

My Phone You
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Lab 4: Music Player

Version 1.0 – David Black-Schaffer


Version 1.2 – David Black-Schaffer, 12 Feb 2007
Version 1.3 – David Black-Schaffer, 19 Feb 2007
Version 1.5 – Ben Nham, 22 Oct 2007

Introduction
In this lab you will implement a music player. The music player will take songs stored in a ROM consisting of
notes and durations, look up the frequency for the note in a ROM, and then play them through a speaker using a
sine ROM to synthesize a sine wave of the appropriate frequency. The sine wave output will give you pure
tones. In the final project you’ll add harmonics and dynamics to create more realistic voices.

You will be reusing the modules you develop for lab 4 in both lab 5 and your final project, so it is important that
you stick to the interfaces we give you. (If you think you need a different interface chances are you’re doing
something wrong so please talk to the TAs.)

This is a much larger lab than anything you’ve done so far, so we’re providing you with a bunch of helpful
starter files, including the whole music_player module. 1 Make sure you look through the provided files before
you get started. Also, since the lab is very large, you’ll probably want to work in parallel with your partner at
times. The interfaces between all major modules are defined, which makes working in parallel easier.

Overview
The music_player module is the top-level2 of your design and contains 4 sub-modules, the master control unit
(mcu), the song_reader, the note_player, and the codec_conditioner. It is important to understand the flow of
events in this system so you will understand the role of each module.

There are two types of events that drive your system: button presses (play or next_song) and new_frame signals
from the audio chip on the board. In response to these three inputs your music_player will output the right audio
samples at the right time.

Here is a high-level block diagram of music_player:

music_player

buttons play, song play, note sample sample


AC97
Audio
codec_
mcu song_reader note_player Interface
conditioner
(provided)
(provided) 48 kHz
song done note done next sample new_frame

Let’s run through a sample set of inputs and responses from music_player to figure out the behavior of the
system. Make sure you see how the steps correspond with the arrows in the diagram.

First, examine the diagram from left to right to see how samples, songs and notes are selected:

1
Before you get too excited I should mention that all the music_player module does is hook up the sub-
modules, so while this will save you a bunch of typing it isn’t really the whole assignment.
2
When you synthesize your design for the FPGA you should use the lab4_top.v file as it contains all the
inputs/outputs to the actual FGPA.
Page 1 of 11
Lab 4: Music Player
1. The user pushes the play button, which is read by the mcu.
2. The mcu tells the song_reader to play one of the four available songs..
3. The song reader gets the first note of the selected song from an internal song_rom module, and passes
the first note along with a play signal to the note_player.
4. The note_player sees the play signal and the note, and looks up the frequency associated with that note
from an internal frequency_rom module. It passes the frequency into an internal sine_reader module that
calculates the actual audio sample for a sine wave of that frequency. It then waits for codec_conditioner
to request the next sample, and then passes the next sample to the codec_conditioner.

So, now we’ve output a single sample of a single note from a single song. When do the samples, notes, and
songs change? To understand this, follow the diagram from the right to left:
1. A 48 kHz new_frame input from the AC97 audio chip on the FPGA goes high for a cycle.
2. The codec_conditioner sees the new_frame input and asks note_player to pass it the next 48 kHz sample
of the current note.
3. When the note_player finishes the current note (which happens when the codec_conditioner has asked it
for enough samples) it tells the song_reader that it is done with the note.
4. The song_reader then tells the note_player what the next note is.
5. When the song_reader is done with a song (which happens when the note_player has asked for enough
notes) it tells the mcu that the song is done.
6. The mcu is then responsible for telling the song_reader to go on to the next song when the appropriate
button is pressed.

This event flow is critical for understanding how this system works together. Remember that the audio codec
requests new samples and the buttons control the state of the system. Note how nicely this breaks down your
system. Once we have defined the interface between each of these blocks you can write them independently and
test them independently before you hook them up.

So let’s dive into each one in turn.

The Master Control Unit (MCU)


The MCU has two tasks: controlling the state of the overall system in response to the button presses and
keeping track of which song is currently being played.

MCU Interface:
Signal Direction Description
clk Input Clock signal
reset Input Reset signal
play_button Input A one-cycle pulse indicating the play button has been pressed
next_button Input A one-cycle pulse indicating the next_button has been pressed
play Output True if the system should be playing, false if no output should be
generated
reset_player Output Goes high when the player is moving on to the next song to reset the
other parts of the system so they aren’t in the middle of something else.
song_done Input From the song_reader indicating that the current song has finished.
state[1:0] Output This is a debug output. You should send the current state of your FSM
to this.
song[1:0] Output The song to play.

Page 2 of 11
Lab 4: Music Player
The MCU is responsible for starting off paused when the system is reset. Whenever the system is paused it
should output no audio. (That is, you should just hold the current sample steady—since this will be a DC signal,
you’ll hear only silence.) When the play button is pressed it will begin playing the current song. If the play
button is pressed while playing the song it will pause, and resume at the same point when play is pressed again.
(This is what the play output is for.) When the song finishes it should wait in the paused state at the beginning
of the song. If the next button is pressed at any time it will go to the beginning of the next song and pause there.
After song 3 the MCU should return to song 0. (This is trivial: just let your song counter wrap around).

The Song Reader


The song_reader is responsible for reading the song out of the provided song_rom. The song_rom has 128
entries of 12 bits each. Each address is a note, in the format of {6’note, 6’duration} where the note represents a
note in the frequency_rom in the note_player, and the duration is the length of the note in 48ths of a second.
The song_rom is divided into 4 songs, each of 32 notes. A song that is shorter than 32 notes must be filled wit h
0-length notes at the end. Take a look at the song_rom file for the details.

The song_reader takes in the number of the song to play from the MCU and looks up the first note in the
song_rom. (Remember that the song_rom takes one cycle to return the data!) It then sends the new note and the
duration on to the note_player. The song_reader then waits for the note_player to tell it that it has finished the
note. At this point it looks up the next note and sends it to the note_player. This repeats until the song_reader
has finished the current song, at which point it tells the MCU that the song is done.

When you implement your song_reader it is essential that you draw a timing diagram that shows what states
your FSM is going through and when the data is ready from the song_rom. Otherwise you will end up sending
the wrong note to the note_player. (See the section at the end about timing diagrams.) You should instantiate the
song_rom within the song_reader since it is the only module that will be using the song_rom.

For example, here are some entries from the song_rom we’re providing:
Address (7 bits) Value (12 bits) Note Value Duration Value
90 = 10 11010 {6’d43, 6’d6} Note 43 = D# or Eb 4 6/48ths
song 3, note 26
91 = 10 11011 {6’d44, 6’d14} Note 44 = E 4 14/48ths
song 3, note 27
92 = 10 11100 {6’d0, 6’d28} Note 0 = rest (silence) 28/48ths
song 3, note 28

Note how in the address column, the two MSBs map to the song we’re playing, and the bottom 5 bits map to the
current note we’re playing. You should convince yourself that addressing the song_rom in this manner really
splits the 128-entry song_rom into a 4 song by 32 entry matrix of songs.

When the third song is playing and it gets to the 26th note, it will tell the note_player to play the 4th D sharp or
E flat (they’re the same note) for 6/48ths of a second. The next note will be the 4th E for 14/48ths of a second,
followed by silence (rest) for 28/48ths of a second. I’m assuming that everyone has been exposed to basic music
notation and understands what an A# or Bb is. If you don’t have any idea about these you should be sure to look
them up or ask the staff.

Both the song_rom and the frequency_rom are generated using the song_rom worksheet Excel document, so
you can easily modify them. (Indeed you need to create a fourth song to complete the lab, but it doesn’t have to
be any good—if you’re lazy or don’t have much time, just make it a scale.)

Page 3 of 11
Lab 4: Music Player
Song Reader Interface:
Signal Direction Description
clk Input Clock signal
reset Input Reset signal
play Input True if the song reader should be playing.
song[1:0] Input The song to play.
song_done Output True if the song has finished.
note[5:0] Output The note from the song_rom to play now. The frequency_rom
looks up this note to find the step size to use to generate the sine
wave output.
duration[5:0] Output The duration for the note from the song_rom to play now.
new_note Output One cycle pulse that tells the note_player to latch in the values
on note and duration and start playing that note.
current_note_and_song[6:0] Output A concatenation of the current song (MSBs) and the address of
the current note (LSBs) being played. This is displayed on the
7-segment LEDs on the board for your amusement. Note that
this is the address of the note and note the note itself.
note_done Input From the note_player to indicate that the note has finished and
that it is ready for the next note.
state[2:0] Output The internal state of your song_player, used for debugging.

Hint: if you have a state in your song reader that you go through for one cycle whenever you change notes, you
can add a $display statement to it which could output something along the lines of $display(―Playing note %d
of song %d, which is note %d duration %d‖, note_address, song, note, duration);. That way whenever you were
debugging it would tell you what note it was playing. The $display statement will be ignored by the Xilinx
synthesizer, so you don’t have to worry about the fact that it’s not synthesizable.

Note Player
Here is a sketch of some of the internal components and wires you’ll need in your note player:

Page 4 of 11
Lab 4: Music Player
The note_player is the central part of this lab. Its responsibility is to take in a note, look up the step size required
to generate the correct frequency for that note in the frequency_rom, and then synthesize a sine wave at that
frequency by using the step size to walk through the sine wave in the sine_rom.

To make this simpler you will design a separate module (the sine_reader) which takes in the frequency and
generates the individual samples. If we pull out the sine_reader, it simplifies the note_player so all it needs to do
is store the current note and duration it receives from the song_reader, keep playing it for the duration of the
note, and then tell the song_reader it’s done. When the note_player gets the note it needs to look up the step size
for the note in the frequency_rom and send that off to the sine_reader. The note_player also needs a counter to
keep track of the duration of the note it is playing. This counter counts down every 48th of a second that the
note is playing (remember that if we pause we don’t keep counting down). The 48th beats are generated by a
beat_generator module (which we provide). The beat_generator uses the same signal from the
codec_conditioner to generate its beat.

Note Player Interface:


Signal Direction Description
clk input clock
reset input reset signal
Play_enable Input True if the note should be playing
Note_to_load[5:0] Input The note to load
Duration_to_load[5:0] Input The duration to load
Load_new_note Input Goes high when we have a new note to load
Done_with_note Output Goes high when we have finished playing our note
Beat Input Goes high for one cycle at 48Hz
Generate_next_sample Input From the codec_conditioner telling us to generate and output the next
sample
Sample_out[15:0] Output The 16-bit audio sample output
New_sample_ready Output Tells the codec_conditioner that we have a new sample ready for it.
State[5:0] Output Debugging output of your state.

Sine Reader
The sine_reader is a sub-module of the note_player which takes in a step size and generates a repeating sine
wave that steps through the sine wave, generating a frequency determined by the step size. This is really pretty
simple. We have a sine ROM which takes in an address and produces a sample of the sine wave. Therefore, if
we address the sine ROM correctly, we can generate sine waves of arbitrary frequency. For every 48 kHz
generate_next pulse that we get, we have to increment the address pointer into our sine ROM by a certain step
size. If we increment our address pointer by a larger step size, we walk through the sine wave faster, and we
generate a higher frequency sine wave. If we increment our address pointer by a smaller step size, we walk
through the sine wave slower, and generate a lower frequency sine wave. The output of our module is just the
output of the sine ROM.

This sounds relatively simple, but there are three complications with the sine reader. First, the sine_rom takes
one cycle to output its value, so you need to make sure you’re thinking about this when you design your logic.
(Draw a timing diagram to figure out the timing.)

Secondly, the sine_rom only has 1024 samples, which means it has a 10 bit address signal. However, we need
more than 10 bits of precision to make precise tones. For example, we might want to increment the address of
the sine ROM by 10.5 for every 48 kHz pulse, rather than by just 10 (if we truncate the bits). So after two
Page 5 of 11
Lab 4: Music Player
pulses, we want to increment the address by 21 (10.5 * 2), rather than by 20 (10 * 2). To do this, we must keep
extra bits of precision around. We will use a 10.10 binary fixed point signal for our step size. We will keep our
address counter 20 bits wide, but we’ll only use the upper 10 bits to actually address the sine ROM.

Let’s run through the above example of using a tep size of 10.5 (0000001010.1000000000). Our first addition
will give us address 10:

current address + step size = next address


0000000000.0000000000 + 0000001010.1000000000 = 0000001010.1000000000

We only use the top 10 bits (0000001010 = 10’d10) as the address to the sine_rom.

Our second addition will give us 21:

current address + step size = next address


0000001010.1000000000 + 0000001010.1000000000 = 0000010101.0000000000

Again, we only use the top 10 bits as the address to the sine_rom, which are 0000010101 = 10’d21.

Since that we can interpret bits however we want, there’s nothing special about treating the 20-bit step size
input as a 10.10 number, as long as the input was calculated as a 10.10 number. The frequency_rom that
provides the step_size is calculated such that the output is a 10.10 step size, so this works for you out of the box.

So in the end, we basically end up using a 20 bit counter and take the top 10 bits off as the address—except that
there’s one more complication.

The sine ROM does not store an entire sine wave. Instead, it stores a quarter sine wave. From the quarter sine
wave, you have to generate the other three quadrants of the sine wave.

We can deal with this the same way we’ve dealt with the step size—by using extra bits of precision. We add
two new most significant bits to our 20 bit counter to make it 22 bits wide. We use the top two bits to denote
which quadrant of the sine wave we’re in:

Q Raw addr Precision


01 0000001010 1000000000

Q – 2 bits that specify the quadrant of the sine wave that we’re in
Raw address – 10 bits that specify the address we need
Precision – 10 bits that we keep around just for precision.

Therefore, in the end, we need a 22 bit flip flop to store the address bits for our counter, and 22 bit next address
and 22 bit current address signals going into the D and Q ports of the DFF, respectively.

Depending on the quadrant of the sine wave we’re in, we change either the address into the sine ROM or the
result out of the sine ROM accordingly. If we are in the first quadrant of the sine wave, we can feed in the raw
address into the sine ROM and leave the output of the quarter sine ROM unmodified. For the other quadrants,
we see that the data coming out is either flipped horizontally or vertically, or both. So we need to modify the
address going into the sine ROM (to flip the sine wave horizontally), or the data coming out of the sine ROM (if
we want to flip the sine wave vertically). Here is a sketch and a chart to get you started.
Page 6 of 11
Lab 4: Music Player

Quadrant Address into Sine ROM Output of Module


00 raw_address sine_rom_output
01 <fill out> <fill out>
10 <fill out> <fill out>
11 <fill out> <fill out>

If you need to negate a signal remember 0 minus a value gives you the negative of that value. You should not
use multipliers anywhere in this lab.

The sine_reader is the most complicated part of this project, but it’s also the most fun to debug. When you are
working in ModelSim you can display the output as a sine wave by right-clicking on it and choosing Properties
and then setting the formatting as follows: Height:80, Analog Step, Offset: 40000.0, Scale: 0.001. You’ll then
an analog sine wave on screen. Once you’ve got your waveform all set up in ModelSim you can save it to a .do
file so you can easily re-load the display configuration later. This will prevent you from having to re-add the
signals every time you run ModelSim.

Sine Reader Interface:


Signal Direction Description
clk input clock
reset input reset signal
Step_size[19:0] Input The step by which we count each time. This is the frequency.
Generate_next Input True when we should generate the next sample.
Sample_ready Output True if we have a sample ready to output. (Remember the sine_rom
takes a cycle!)
Sample[15:0] Output The sample we’ve generated.

Codec Conditioner
So far I haven’t mentioned anything about how your design interfaces with the actual audio hardware on the
FPGA board. This is done through the ac_97if module. This module gives you a new_ frame signal which goes
Page 7 of 11
Lab 4: Music Player
high every time you’re supposed to provide a new sample. The tricky part is that you are supposed to provide a
new sample as soon as it goes high and not change it until it goes high again. This is a pain.

Remember all those times I’ve mentioned that your ROM takes one cycle to output its value? Well, how are you
supposed to provide the next value immediately when new_frame goes high if you need one cycle to get
through the sine_rom, one cycle through the frequency_rom, and possibly one cycle through the song_rom?
Well, the solution is that you’ll have a codec_conditioner. This module simply has two registers. The current
sample is output from one of them, and the other is where you write the next sample whenever you get around
to it. That way when the next new_frame signal comes in, the codec_conditioner just copies the next value into
the current one and tells the note_player to generate the next one. As long as you can generate the next value
before the next new_frame comes along it will all work. And that shouldn’t be a problem.

You are generating audio at 48kHz. The clock on the FPGA runs at 100MHz. That means you have 2083 cycles
between each new_frame. With the codec_conditioner you have 2083 cycles to generate the next sample before
anything bad happens. This should be plenty of time. Note that I mentioned that the _generator runs off this
signal as well. This is convenient because it means that instead of having to divide 100MHz down to 48Hz we
only have to divide 48kHz down to 48Hz. It also means that if the audio chips clock drifts a little bit we’ll still
be in sync with it.

To make this lab a bit easier we’re providing you with the codec_conditioner module. We’re providing the
ac_97if module as an .ngc file, which is a pre-compiled netlist. All you have to do to use this is add the
ac_97if.v to your Xilinx project and your ac_97if.ngc files into your Xilinx project directory. (However, if you
use the ―clean up project files‖ command you’ll have to copy the .ngc file back again.) We also provide a
codec_sim.v module which simulates the codec with a new_frame every 5 cycles for faster simulations.

Codec Conditioner Interface:


Signal Direction Description
clk input Clock
reset input reset signal
New_sample_in[15:0] Input The new sample to send to the codec on the next new_frame
Latch_new_sample_in Input True when we should latch the data on the new_sample_in input.
Valid_sample[15:0] Output The always-valid sample we present to the ac97 codec.
New_frame Input The input from the ac97 codec that tells us to output the next value.
Generate_next_sample Output Tells the note_player that it’s time to generate the next sample. This
combined with the latch_new_sample_in constitute a handshake
between the codec_conditioner and the note_player.
Note: the ac_97if.ngc may generate a few warnings about equivalent registers. You can safely ignore these.

Other Details…
There are a few other details you’ll have to take care of for this lab. The first one is that you’ll need to
synchronize, debounce, and one-pulse your inputs from the buttons on the board before using them in your
FSMs. Remember that the mechanical buttons on the FPGA board are really little springs, and that when you
press one down it will bounce up and down randomly for about 20ms. (That’s 2,000 clocks.) If you don’t
debounce them you will get somewhere between 1 and 2,000 button presses into your FSM every time you
press a button. We’ve provided a button_press_unit module which chains together a brute_force_synchronizer,
a debouncer, and a one_pulse module. This is instantiated for both buttons in the top level module as follows to
provide clean inputs for you. (This is the same module you used in lab 3.)

Page 8 of 11
Lab 4: Music Player
lab4_top

left_button play sample


button_press_unit
ac97_if
codec
right_button next connections
new_frame
button_press_unit
music_player
current song
up_button = ~reset and note
led_display_
driver 7 segment
clk
displays

We’ve also provided you with a music_player module which already hooks up all of the sub-modules. You
should not need to modify this. This module has an output called new_sample which may generate a warning
saying it is assigned but not used when you compile it in ISE. Don’t worry about this. You will need this output
for lab 5 to determine when you should start capturing the wave for the VGA display.

It would also be nice if you could see what your design is doing on the FPGA, although you should have done
all your debugging in ModelSim. To help out I’ve provided an led_display_driver module which outputs four 4 -
bit numbers to the four 7-segment displays on the FPGA board. The current_note_and_song from the
song_player goes into it so you see the song on the left and which note you’re playing on the right. This is all
set up for you in the top level file, but please take a look at it and feel free to modify it if you can think of
anything cooler.

If you can’t get your design to work we’ve provided a ChipScope interface in the music_player module and a
ChipScope project file. This will allow you to see what’s going on inside your design while it’s running, but this
is a very painful way to debug so don’t plan on using it. The ChipScope modules (ila and icon) may generate
warnings when you compile. You may ignore these.

What you need to do…


Read this whole document. At least twice. Please don’t read the list below until you’ve read all of the above.

1. Understand all the signals for each module. In particular how they flow and what causes them to change.
2. Draw FSM state diagrams for each module which requires an FSM.**
3. Draw timing diagrams for the song_reader, note_player, and sine_reader showing the delay in reading
from the ROMs.**
4. Implement the mcu, song_reader, note_player, and sine_reader.*
5. Write test benches for all of the above, and include the output in your report as well as the testbenches
themselves.*
6. After those test benches work, run the provided top-level test bench to make sure your whole system
works.* (We’ve provided a .do file which you can open in the Wave view in ModelSim to load all the
signals automatically. When you’re simulating the top-level file you can load it into your wave window
with the open command. This test bench takes a long time to run...)
7. Write a song of your choice for song 4. (There is a provided Excel spreadsheet which makes writing
songs trivial: you can literally just type in A B C D E F G to get a scale, for example.)

Page 9 of 11
Lab 4: Music Player
All of the above marked with an * need to be included electronically in your prelab.
All of the above marked with a ** can be submitted electronically or drawn by hand and handed in during class.

Here’s an example of the output from the provided top-level testbench. Note that you can see the different
frequencies and lengths of the notes playing, as well as the states of the various modules. You should refrain
from running this testbench until you’ve thoroughly tested each of your modules individually as this takes about
6 minutes to run. (Your results may vary depending on what is in your song_rom, and you may want to change
the song_rom to make it easier to debug.)

Timing Diagrams
I’ve mentioned several times in this lab that you need to do timing diagrams for various modules. The point of
the timing diagrams is to make sure that your FSM and your other modules are going to work in sync. Here’s a
simple example to get you started.

We’re going to control the data path shown below with the FSM shown below. The idea is that we read
sequential values out of the ROM by incrementing the address counter until the first bit from the ROM’s output
(done) is a 1. Then we keep that value and go to the Wait state. This is pretty close to the FSM in the
song_reader, and is actually part of one of the FSMs in the final project.

Page 10 of 11
Lab 4: Music Player
Finite State Machine Control Data Path
start button == 1
reset
ROM
Wait 0 = {0, 00001}
data out =
1 = {1, 01011}
Increment Check
increment_address address 2 = {0, 00110} {done, value}
Address Done 3 = {0, 00111}
counter …

done == 0

clock

done == 1
So at first glance this looks like it will work pretty well. We are in Wait until the button is pressed, then we
increment the address, then check if we’re done. If we’re done we go back to Wait, otherwise we increment the
address again and repeat. No problem. Unfortunately this will not work. To see why, we make a timing
diagram. We assume the system is reset at the beginning and that the only input is the start button being pressed
in cycle zero. Here’s the timing diagram for our system:

Cycle Start Increment Address Data out State


button address
0 1 0 0 {0, 00001} Wait
1 0 1 (A) 0 {0, 00001} Increment Address
2 0 0 1 (B) {0, 00001} Check Done
3 0 0 1 {1, 01011} (C) Increment Address
4 0 1 (D) 1 {1, 01011} Check Done
5 0 0 2 (E) {1, 01011} Wait
6 0 0 2 {0, 00110} (F) Wait

Notice two things: it takes 1 cycle for the address to change when we assert increment address, and it takes 1
cycle for the ROM data to change after we change its address. What this means is that the done bit we’re
checking in the Check Done state is not the one from the new address! (In cycle 2 above, we’re still seeing the
data out from the previous address.) The way to see this is to notice in the timing diagram above that one cycle
after we assert increment address (A) we see the address increment (B) and one cycle after that (C) we see the
new data from the ROM. The same thing happens later with DEF. To fix this we need to change the FSM so
that it waits to check the data out only after it has had time to let the address increment and the new data
become available. You will run into exactly this issue anywhere you use a module (such as a ROM, timer, or
counter) that updates on the next cycle!

Page 11 of 11

You might also like