SlideShare a Scribd company logo
Final Project
Serial to Morse Code Converter
Engs 31: Digital Electronics
June 2020
Students:
Hana Ba-Sabaa
Sayuri Tais Miyamoto Magnabosco
Professor:
Geoffrey Luke
Abstract:
The Morse code is a method of communication using binary signals that encode text
characters as standardized sequences of two different signal durations, called ​dots and ​dashes​.
The goal of this project is to create a serial to Morse code translator using VHDL code,
WaveForms software, AD2 board, and a Basys-3 FPGA integrated circuit board. Our system
is able to store up 100 characters of input, which can be released at any moment by the ​enter
key. In order to facilitate the design and validation of the Morse code converter system, we
followed top-down design and bottom-up implementation. Therefore, the functionality of the
system relies on the correct implementation of 8 small functional blocks: ​SCI Receiver​, ​SCI
Transmitter​, ​Check Characte​r, ​Buffer​,​Morse Translator​, ​Morse interpreter​, ​Square Wave
Oscillator​, and Final MUX. The SCI blocks receive the binary data coming from the AD2
block and concatenate them in ASCII formatting. The characters are then sent back to the
AD2 so the user can see on the screen their input. The SCIs work at a baud rate of 9,600
bits/sec. The Check Character block verifies if the ​enter key has been pressed to trigger the
translation of the bits in the system. The Buffer stores the characters inputted by the user,
while the translator transforms each bit into its Morse code equivalent – a representation of
dots (01) and dashes (11). The Interpreter uses such formatting as a time indicator for the
sound and light signals. The ​Square Wave Oscillator and Final MUX blocks take care of the
audio aspect of the system. They generate square waveforms with ideal frequencies to form
pitches recognizable to human ears (500Hz). The result of each component block is satisfying
and in alignment with the specifications for the whole system. Our design went through
synthesis, implementation and bitstream generation successfully. We also programmed our
board accordingly. However, during the demonstration, our board did not behave as expected.
We believe that the problem may have been with our wiring.
1
Table of Contents:
Introduction 3
Approach 4
System Design 4
Signal Generation and the AD2 Board 5
SCI Receiver 5
SCI Transmitter 7
Check Character 10
Buffer 10
Morse Translator 10
Morse interpreter 11
Square Wave Oscillator 13
Final MUX 13
Memory Map 13
Testing 13
Conclusions 33
Acknowledgements 33
Appendix (VHDL Code): 33
SCI Receiver 33
SCI Transmitter 45
Check Character 56
Buffer 58
Morse Translator 62
Morse Interpreter 67
Square Wave Oscillator 82
Final MUX 83
Final Top Code (Shell File) 84
2
Introduction
The device designed for this project is a Serial to Morse Code Converter. Using the
Serial Communications Interface (SCI), the user inputs characters into the system and the
device outputs the Morse code signal for it. The circuitry designed receives the character data
and converts it into an encoded format using binary signals. This step allows the read out of
the character in terms of dots and dashes, regulated by a precise timing. In this design, the
fundamental unit of time, 𝑇, is 0.1 s long.
The inputs of the circuitry are a 10MHz master clock and a 1 bit-signal coming from
the AD2 board. Each bit received from the AD2 board is stored in a shift register at a baud
rate of 9,600 bits/sec. The outputs of the system are a light and sound signal, a “full” signal
that lights up a LED when the user inputted 100 chracter, as well as a 1-bit signal that serially
transmits back to the AD2 the character originally inputted by the user. We also have an
end_tick to indicate when all the bits of the character were sent back to the AD2. This is
represented by the schematics below:
The system has a buffer that stores up to 100 characters. To have the message
decoded in sound and light format, the user must press enter and wait until all the characters
have been outputted to start writing again. If the user inputs 100 characters, the buffer gets
full and a LED lights up on the board to indicate that. In case the user keeps writing, the
characters will not be saved in the buffer and will be lost. To release the message stored, the
user must press the enter key. If the enter key is never pressed, then the “full” light will be
off. Our system converts both lower and upper case letters, and numbers 0-9. Any other
character will be recognized and outputted as zero.
3
Approach
In order to facilitate the design and validation of the morse code converter system, we
follow top-down design and bottom-up implementation. We broke down the system into the
following small components and built and tested each one of them individually:
1. Signal Generation and the AD2 Board
2. SCI Receiver
3. SCI Transmitter
4. Check Characte​r
5. Buffer
6. Morse Translator
7. Morse interpreter
8. Square Wave Oscillator
9. Final MUX
For the components that needed a controller and a datapath, each part was designed and
tested separately using the EDAPlayground platform. Each component was then individually
wired and tested in Vivado for validation. After confirming that each part was matching the
design specifications, we built a shell and wired all the signals together in order to have a
working system.
Our team communicated daily and split the work accordingly. Components 2, 3, 7, and 8
were the main responsibility of Sayuri, while components 1, 4, 5, 6, and 9 were the main
responsibility of Hana. We would frequently meet and chat to discuss which signals were
needed in each component so our overall system would connect. Additionally, we helped
each other in code debugging and coordinated to attend TA hours together.
System Design
The following block diagram represents the overall architecture of the system:
4
1. Signal Generation and the AD2 Board
In order to decide what letters the Morse code generator will make, the user sends
characters to the Basys3 board using the Serial Communications Interface (SCI). The SCI
signal is generated using the WaveForms software and the AD2 board, and sent to one
digital I/O pin on the Basys3. Each character entered is converted into the form of an 8-bit
ASCII character. Subsequently, the AD2 board outputs each bit of the character, one at a
time. This part does not require any VHDL design.
2. SCI Receiver
The SCI Receiver is a 10-bit shift register that takes in one bit at a time from the AD2
board, at the baud rate of 9,600 bits/sec, concatenates them into a single vector, removes the
start bit and stop bits, and shifts the 8-bit character result. The process is controlled by a state
machine. The receiver’s inputs are the serial data stream from the AD2 and a 10 MHz master
clock. Its outputs are the 8-bit data, in parallel, and a done_tick signal that goes high when the
output is ready. This is summarized by the following diagram:
5
a. Double Flop Synchronizer
Designed accordingly to the following schematics to provide an additional
clock period and resolve the metastability in the process.
b. Datapath
The serial data coming from the AD2 board is right-shifted into a 10-bit shift
register, called shift_reg, ​which is clocked by the 10 MHz clock, and enabled by a
signal ​shift_en from the controller. It has a ​shift_clr input for resetting. The bits 8
down to 1 of the shift register may be parallel-loaded out when enabled by the control
signal ​output_en.
c. Controller
The controller consists of a 6-state finite state machine and three counters, as
summarized in the diagram at the end of this section.
The “waiting” states were programmed to follow the baud rate of 9,600
bits/sec. In these states, the machine counts clock edges to locate the center of each
data bit. For the first bit, it counts ​N​/2 clock edges, while for the remaining bits, it
counts up to N clock edges. Additionally, the machine relies on the counter that keeps
track of how many bits have been transmitted and stored in the shift register. When
there is the start bit + 9 other bits inside the register (count_shift=8), ​output_en goes
high so the datapath outputs the 8-bit ASCII character.
Each time the controller receives the start bit from the AD2 (​data_in_sync =
0​), it leaves its idle state and goes to its ​wait_start_bit state. In this state, ​shift_en goes
high and the start bit is stored in the shift register.
The machine stays in ​wait_start_bit state for half T (520 clock cycles, based
on the 10 MHz clk period) until ​count_half_T signal goes high; the machine then
moves to the ​shift_reg state. In ​shift_reg, the ​shift_en goes high and allows the bit
coming from the AD2 to be stored in the shift register. The machine then enters the
wait_other_bits state, where it waits for T (1042 clk cycles, based on the 10 MHz
clk), then ​count_T goes high and the machine returns to the ​shift_reg ​state to receive a
new bit.
After 10 bits of data have been put into the shift register, the machine moves
to ​shift_output state, where ​output_en ​goes high and the 8-bit ASCII code is parallely
shifted out of the register. Additionally, the output ​done_tick ​goes high to signal that
6
the ASCII data is available. Then, it goes to the ​clear state and returns to ​idle to wait
for the next start bit.
3. SCI Transmitter
The SCI Transmitter gets the 8-bit character signal from the SCI Transmitter and
sends it back to the AD2, in order to confirm to the user that the system is correctly storing
7
the character they input. Therefore, the transmitter works in reverse to the receiver; its inputs
are the 8-bit data, in parallel, and the done_tick signal from the SCI Receiver, indicating that
a new character is ready. Its outputs are ten 1-bit serial data at the same baud rate of 9,600
bits/sec, and an end_tick that goes high when the last bit of the character is sent to the AD2.
The transmitter consists of a 10-bit shift register that takes the 8-bit signal from the
receiver, concatenates it with a start and end bits (start = 0; end =1), and outputs one bit at a
time by left shifting the bits out of the register. This is summarized by the following diagram:
a. Double Flop Synchronizer
Designed to provide an additional clock period and resolve the metastability in
the process, following the schematics of the SCI Receiver flop synchronizer.
b. Datapath
The parallel data coming from the SCI Receiver is concatenated with a start
and end bit into a 10-bit register​, ​which is clocked by the 10 MHz clock, and enabled
by a signal ​load_en from the controller. It has a ​reg_clr input for resetting. The bits
inside the shift register may be loaded out serially by right-shifting when enabled by
the control signal ​output_en.
c. Controller
The controller consists of a 5-state finite state machine and two counters, as
explained in the diagram below:
8
The ​wait_T state was programmed to follow the baud rate of 9,600 bits/sec. In
this state, the machine counts up to N clock edges before output-shifting each bit.
Another counter that regulates the state machine is the ​count_shift​, which keeps track
of how many bits have been output back to the AD2.
Each time the controller receives the high signal of ​done_tick from the SCI
Receiver, it leaves its idle state and goes to its ​shift_load state. Here, ​load_en signal
goes high which allows the datapath to get the 8-bit data coming from the SCI
Receiver and concatenate it with a start and end bits into a 10-bit register. The
machine then moves to ​shift_nums state, where ​output_en goes high and triggers the
right-shifting out of a single bit. Subsequently, it goes to wait_T state, where it waits
9
for T (1042 clk cycles, based on the 10 MHz clk), then ​count_T goes high and the
machine returns to the ​shift_nums ​state to output another bit. After 10 bits of data
have been outputted (c​ount_shift​=9), the machine goes to the ​clear state, where
reg_clr ​and ​end_tick ​go high to signal that all the bits of that character have been
transmitted. Then, the controller returns to ​idle​ to wait for another character.
4. Check Character
This block checks whether the character coming from the SCI Receiver is an enter
key or not. If it is, the check_character block will output a signal, ​read_en​, with a logic high,
which will later enable the buffer to read all the characters that have been previously stored in
the queue.
5. Buffer
The buffer is a 101 characters long 8-bit queue that stores the characters inputted by
the user until they press the enter key. When the user inputs 100 characters successfully , that
is they terminate their input with an enter key, a signal called ‘full’ (having a logic high) is
outputted by this buffer. This signal turns on an LED light on the board, which indicates to
the user that their input has been successfully saved in the queue.
The buffer is designed so that it only stores data in the queue both if a new character
is inputted by the user and there is space left in the queue. Therefore, if the user inputs 100
characters and forgets to press the enter key, their characters will not be stored in the queue
and, accordingly, their Morse code equivalent will never be outputted. To test our code, we
modified the queue so that it is 6 characters long.
6. Morse Translator
This block takes the data_out 8-bit signal
coming from the buffer and translates the ASCII that
the signal represents to its Morse code equivalent.
Using the table provided to us in the project handout,
we hard coded the Morse combination of dots and
dashes for each character (letters and numbers).
We represented dots with 01 and dashes with
11. Because the Morse code characters have different
lengths (the letter E is only a dot, while the number
zero is 5 dashes), our Morse code is 10-bits long, to
accommodate the longest characters. Accordingly, if
a character has less dots and dashes, 00 can be used
10
to pad it and ensure it is the same length as the other longer characters.
We also accounted for lowercase letters, which will translate to their uppercase Morse
code equivalents. In case a random character is inputted by the user, this block will output the
Morse code of a zero, i.e., 11 11 11 11 11.
7. Morse interpreter
This component receives the data coming from the translator and interprets the 01, 11,
and 00 bits of the data as a time indicator for the sound and light signals.
The speed of the Morse code is determined by a time T=0.1s. A dot is on for 𝑇 and
dash is on for 3𝑇. In between dots and dashes within a single letter there is a gap of 𝑇. In
between letters there is a gap of 3𝑇. In between words there is a gap of 7𝑇.
Its inputs are the 10-bit data from the translator, and ​translation_done ​tick that
indicates a new character was translated. It outputs signals for sound and light, and an
end_trans tick that goes high whenever the character is done being interpreted. This
component consists of a register and a controller. The register consists of a 10-bit shift
register that takes the 10-bit signal from the translator, reads and shifts the two left-most bits,
and outputs them as dots (01), dashes (11), or end of character (00). Intermediate signals
trigger the state machine and the datapath as demonstrated in the diagram below:
a. Datapath
The parallel data coming from the Translator is put into the register, which is clocked
by the 10 MHz clock, and enabled by a signal ​load_en from the controller. If the
character is a space (all zeros), then the register sends the signal ​space to the
controller; otherwise, it sends the signal ​no_space​. Triggered by the signal
check_bits_en from the controller, the datapath analyzes the bits 9 down to 8 of the
register; if they are 01, it outputs the signal ​dot as high; if they are 11, it outputs ​dash
as high; if they are 00; it outputs ​end_char as high. The signal ​shift_en triggers the
left-shift of the two left-most bits of the register, so the next two bits can be decoded.
The signals ​count_T_en​, c​ount_3T_en​, and ​count_7T_en, ​dictate when ​light and
11
sound signals will be high or low and for how long, following the speed of the Morse
code of T=0.1s.
b. Controller
The controller consists of a 10-state finite state machine and several counters to mark
the time for dots and dashes for each character, as explained in the diagram below:
The “timing” states were programmed to follow the speed of the morse code
as T=0.1s. In these states, the machine counts clock edges up to T, 3T, or 7T.
Each time the translator has a new character available, (​translation_done = 1​),
it leaves its idle state and goes to its ​shift_register ​state. In this state, ​load_en goes
high so the data from the translator is stored in the register in the datapath. If the
character we receive is a space, ​space=1 and we move to ​time_7T state. The machine
stays in this state for 0.7s until count_7T_TC goes high and the machine moves to the
clear​ state.
However, if the data received is not a space character, ​not_space=1​, and the
machine moves to ​check_bits ​state. Here, ​check_bits_en goes high and we receive
back from the datapath the information of whether we have a ​dot​, a ​dash, ​or the
end_char​.
12
A. If ​dash=1​, we move to t​ime_3T state. We stay in this state for 0.3s,
held by a counter. When ​count_3T_TC = 1, we move to
time_within_letters​ state.
B. If ​dot=1​, we move to ​time_T state. We stay in this state for 0.1s, held
by a counter. When ​count_T_TC = 1, we move to ​time_within_letters
state.
C. If ​end_char=1​, we move to ​time_between_letters state. We stay here
for 0.3s. Then ​count_between_letters_TC goes high and we move to
the ​clear ​state.
In the time_within_letters state, the signal ​count_within_char_en=1, ​which
triggers the count of clk cycles up to 0.3s. Then, the terminal count goes high and we
move to the ​shift_bits state. Here, the signal ​shift_en goes high and allows for the bis
in the shift register in the datapath to shift left and expose the next encoded morse
signal. Then, the machine goes back to ​check_bits state to verify the presence of dot,
dash, or end of character bits.
Once in the ​clear state, ​end_trans goes high to indicate we are done outputting
the morse for that character. Then it returns to ​idle​ to wait for the next character.
8. Square Wave Oscillator
This component creates a square wave to output the sound at a frequency of 500Hz,
which is an audible range for human beings. Its input is the master clock at 10MHz and its
output is the ​sound_wave​. The ​sound_wave ​stays high for 2000 clk cycles.
9. Final MUX
This component “AND” the ​sound_wave signal from the Square Wave Oscillator and
the ​sound signal coming out of the Morse interpreter, so we only have audible sound while
the ​sound ​signal is high.
Memory Map
In this design, we used 4 10-bit registers for the SCI receiver and transmitter. For the
queue, we had to have enough memory to store 8bits *100. For the translator, we used
enough memory to encode a 10-bit representation for each character. The following graphs
summarize the post-implementation memory data for our circuitry:
13
Testing
1. Components
When testing each component, we addressed each error and warning message
received, to make sure they would not be a major issue when assembling the whole
system.
a. Signal Generation and the AD2 Board
We connected the receiver and transmitter of the AD2 Board. Below is a
screenshot of our waveform for ‘hello world’.
b. SCI Receiver
14
i. Double Flop Synchronizer
ii. Datapath
15
iii. Controller
16
17
18
c. SCI Transmitter
i. Double Flop Synchronizer
ii. Datapath
19
iii. Controller
20
d. Check Characte​r
e. Buffer
21
22
f. Morse Translator
g. Morse interpreter
i. Datapath:
23
ii. Controller
24
25
26
27
iii. Full Component:
28
h. Square Wave Oscillator
29
i. Full Design
Schematics:
1- ​SCI Receiver
30
2- SCI Transmitter
3- Check Character
3​-Queue
31
4- Translator
32
5- Interpreter
33
2. Overall System
a. Final Schematic of All the Parts Together:
34
Conclusions
Each component of our project successfully meets the requirements specified in the
introduction. When wired together, all the blocks were successfully implemented into the
Basys3 board as well. However, the board did not behave as expected. Both the LEDs for the
Morse code light and for the “full” buffer signal were always on, and no sound was coming
out of the WaveForm software. Because we did not get any error messages through our
implementation and each separate component was behaving as expected, we believe that the
issue was with wiring the board with the AD2 component.
If we were to design this project again, we would modify the code for the buffer, so
the “full” signal for the LED lights up when the user has input 100 chracters and stays on
until the input is the enter ​key. Another modification would be to combine the block “Square
Wave Oscillator” and “Final MUX”, since they both deal with the sound output of the Morse
code. Additionally, we would also include a clock divider on our top shell to slow down the
Basys board clock. We would keep our top-down design and bottom-up implementation, as
we believe it is a good approach to debugging and testing.
Acknowledgements
Throughout the project, we referred back to the projects we built in the lab sections
for guidance on how to break down our system in small components and follow top-down
design and bottom-up implementation. We referred to the slides provided by Professor Luke
to set up the parameters for the WaveForms software and for connecting the Basys3 and the
AD2 component. These slides also guided us to connect the Morse code ​sound_out to the
oscilloscope to play the sound. The buffer was built upon the code we wrote for this year’s
“Exercise 19: Queues”. The SCI Receiver and SCI transmitter were designed by adapting the
instructions of Lab5 of Spring 2016. The XDC file provided in this year’s Lab 4 was used as
a template to generate our own constraints.
We would like to acknowledge the help of TAs Ruthie, Matthew, and Shailin, for
their guidance and support throughout the project. We are also grateful for our classmates
Akwasi and Tyler, who kept us company throughout this project and made sure we always
had fun music playing in Mclaughlin’s common room.
Appendix (VHDL Code):
1. SCI Receiver
a. Double-Flop Synchronizer
i. Code
-- Code your design here
library IEEE;
use IEEE.std_logic_1164.all;
35
ENTITY SCI_receiver_double_flop IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_in : in STD_LOGIC; -- 1bit signal from AD2
data_sync : out STD_LOGIC); -- 1bit signal after being delayed
by 2 clk cycles
end SCI_receiver_double_flop;
architecture behavior of SCI_receiver_double_flop is
--Signals
signal d_in_sync, dsync : std_logic :='0'; -- signals for double flop
synchronizer
BEGIN
-- Double-flop synchronizer
double_flop_sync: process (clk)
begin
if rising_edge(clk) then
dsync <= data_in; -- flop 1
data_sync <= dsync; -- flop 2
end if;
end process;
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
entity SCI_receiver_double_flop_tb is
end SCI_receiver_double_flop_tb;
architecture testbench of SCI_receiver_double_flop_tb is
component SCI_receiver_double_flop
PORT ( clk : in STD_LOGIC; --10MHz clock
data_in : in STD_LOGIC; -- 1bit signal from AD2
data_sync : out STD_LOGIC); -- 1bit signal after being delayed
by 2 clk cycles
end component;
-- signals
signal clk, data_in, data_sync: std_logic := '0';
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut : SCI_receiver_double_flop PORT MAP(
36
clk => clk,
data_in=> data_in,
data_sync=> data_sync);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 1*clk_period;
data_in<='1';
wait for 1*clk_period;
data_in<='0';
wait for 1*clk_period;
data_in<='1';
wait for 1*clk_period;
data_in<='0';
wait for 1*clk_period;
data_in<='1';
wait for 1*clk_period;
data_in<='0';
wait for 1*clk_period;
data_in<='1';
wait for 1*clk_period;
data_in<='0';
wait for 1*clk_period;
end process;
end testbench;
b. Controller
i. code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY SCI_receiver_controller IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync: in STD_LOGIC; -- 1bit signal from double flop
synchronizer
shift_en : out STD_LOGIC; -- send to datapath
shift_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
done_tick : out STD_LOGIC); -- indicates new data is ready
end SCI_receiver_controller;
37
architecture behavior of SCI_receiver_controller is
--signals
type state_type is (idle, wait_start_bit, wait_other_bits, shift_reg,
shift_output, clear); -- states of FSM
signal current_state, next_state : state_type := idle;
signal count_halfT, count_T, count_halfT_en, count_T_en,output_en_signal,
shift_en_signal: std_logic:= '0';
signal count_shift,count_clk_cycles, count_Tclk_cycles: integer:=0;
BEGIN
-- update state machine states
stateUpdate: process(clk)
BEGIN
if rising_edge(clk) then
current_state <= next_state;
end if;
end process stateUpdate;
-- controller
controller: process (current_state,count_halfT, count_T, data_sync,
count_shift)
begin
output_en_signal <= '0';
shift_en_signal <='0';
case (current_state) is
when idle=>
shift_clr<='0';
shift_en<='0';
output_en<='0';
done_tick<='0';
count_halfT_en<='0';
count_T_en <='0';
if data_sync='0' then -- receives start bit
next_state<=wait_start_bit;
end if;
when wait_start_bit=>
shift_clr<='0';
shift_en<='0';
output_en<='0';
done_tick<='0';
count_halfT_en<='1';
count_T_en <='0';
if count_halfT='1' then -- after waited T/2
next_state<=shift_reg;
end if;
38
when wait_other_bits=>
shift_clr<='0';
shift_en<='0';
output_en<='0';
done_tick<='0';
count_halfT_en<='1';
count_T_en <='1';
if count_T='1' then -- after waited T
next_state<=shift_reg;
end if;
when shift_reg=>
shift_clr<='0';
shift_en<='1';
shift_en_signal<='1';
output_en<='0';
done_tick<='0';
count_halfT_en<='1';
count_T_en <='1';
if count_shift = 8 then -- if already input 9 bits
next_state<=shift_output;
else
next_state<=wait_other_bits;
end if;
when shift_output=>
shift_clr<='0';
shift_en<='0';
output_en<='1';
output_en_signal<='1';
done_tick<='1';
count_halfT_en<='0';
count_T_en <='0';
next_state<=clear;
when clear=>
shift_clr<='1'; -- clear shift register
shift_en<='0';
output_en<='0';
done_tick<='0';
count_halfT_en<='0';
count_T_en <='0';
next_state<=idle;
end case;
end process;
-- time we need to wait after receiving 1 bit so it matches a baud rate of
9600
half_time: process (clk, count_halfT_en)
begin
39
if rising_edge (clk) then
if count_halfT_en='1' then
count_clk_cycles <= count_clk_cycles+1;
if count_clk_cycles = 520 then -- num of clk cycles to count for T/2,
based on a 10Mhz clk period
count_halfT <= '1'; -- flags that T/2 has passed; T/2 = (1/2) *
(1/9600)
else
count_halfT<='0';
end if;
if count_clk_cycles = 1041 then -- num of clk cycles (1042 clck cycles)
to count for T, based on a 10Mhz clk period
count_clk_cycles <=0; -- resets counter after reaching 1042 clock
cycles
end if;
end if;
end if;
end process;
-- time we need to wait after receiving other bits so it matches a baud rate
of 9600
full_time: process (clk, count_T_en)
begin
if rising_edge (clk) then
if count_T_en='1' then
count_Tclk_cycles <= count_Tclk_cycles+1;
if count_Tclk_cycles = 1041 then -- num of clk cycles (1042 clck
cycles) to count for T, based on a 10Mhz clk period
count_T<='1'; -- flags that T has passed; T = 1/9600
count_Tclk_cycles <=0; -- resets counter after reaching 208 clock
cycles
else
count_T<='0';
end if;
end if;
end if;
end process;
-- counting the numb of bits in the shift register
bit_count: process (clk, shift_en_signal, output_en_signal)
begin
if rising_edge(clk) then
if shift_en_signal='1' then -- in shift state
count_shift<=count_shift+1;
end if;
if output_en_signal ='1' then -- indicates we have 9 bits of data
count_shift<=0;
end if;
end if;
40
end process;
end behavior;
-- Math for T and T/2:
--T<= 1/9600; -- T for the baud rate in seconds
--num_clk_cycles <= T/(100*10^-9); -- for 2MHz clock
-- 1042 num_clk cycles (rounded up)
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity SCI_receiver_controller_tb is
end SCI_receiver_controller_tb;
architecture testbench of SCI_receiver_controller_tb is
component SCI_receiver_controller
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync: in STD_LOGIC; -- 1bit signal from double flop
synchronizer
shift_en : out STD_LOGIC; -- send to datapath
shift_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
done_tick : out STD_LOGIC);
end component;
-- signals
signal clk, shift_en, shift_clr, output_en, done_tick: std_logic := '0';
signal data_sync: std_logic:= '1';
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut : SCI_receiver_controller PORT MAP(
clk => clk,
data_sync=> data_sync,
shift_en=> shift_en,
shift_clr=>shift_clr,
output_en=>output_en,
done_tick=>done_tick);
41
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 5*clk_period;
data_sync<='0'; -- receives start bit
wait for 1042*clk_period;
data_sync<='1';
wait for 1042*clk_period;
data_sync<='0';
wait for 1042*clk_period;
data_sync<='1';
wait for 1042*clk_period;
data_sync<='0';
wait for 1042*clk_period;
data_sync<='1';
wait for 1042*clk_period;
data_sync<='0';
wait for 1042*clk_period;
data_sync<='1';
wait for 1042*clk_period;
data_sync<='0';
wait for 1042*clk_period;
data_sync<='1';
wait for 1042*clk_period;
wait for 400*clk_period;
end process;
end testbench;
c. Datapath
i. code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY SCI_receiver_datapath IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync : in STD_LOGIC; -- 1bit signal from flop
synchronizer
42
shift_en : in STD_LOGIC; -- receiveing from controller
shift_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of
parallel data
end SCI_receiver_datapath;
architecture behavior of SCI_receiver_datapath is
--Signals
signal shift_reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10
bits
BEGIN
-- Shift and output registers
registers: process (clk, output_en, shift_en, shift_clr)
begin
if rising_edge(clk) then
if shift_clr ='1' then -- clears what is inside the shift register
shift_reg<="0000000000";
elsif shift_clr ='0' then -- if doesn't want to clear the register
if shift_en='1' then -- shift right; most significant bit of
the register gets what is on d_in_sync (the bit coming from AD2 and delayed
by the double-flop)
shift_reg <= data_sync & shift_reg(9 downto 1);
end if;
if output_en ='1' then -- when load register is enabled
data_out <= shift_reg(8 downto 1); -- does not copy start and
end bit
end if;
end if;
end if;
end process;
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity SCI_receiver_datapath_tb is
end SCI_receiver_datapath_tb;
architecture testbench of SCI_receiver_datapath_tb is
43
component SCI_receiver_datapath
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync : in STD_LOGIC; -- 1bit signal from flop
synchronizer
shift_en : in STD_LOGIC; -- receiveing from controller
shift_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
data_out : out STD_LOGIC_VECTOR(7 downto 0));
end component;
-- signals
signal clk, data_sync, shift_en, shift_clr, output_en: std_logic := '0';
signal data_out: std_logic_vector(7 downto 0) := (others=>'0');
constant clk_period: time := 100ns; --10MHz clock
begin
uut : SCI_receiver_datapath PORT MAP(
clk => clk,
data_sync=> data_sync,
shift_en=> shift_en,
shift_clr=>shift_clr,
output_en=>output_en,
data_out=>data_out);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
shift_en<='1'; -- allows shift register to receive the data
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
data_sync<='0';
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
data_sync<='0';
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
data_sync<='0';
wait for 1*clk_period;
44
data_sync<='1';
wait for 1*clk_period;
data_sync<='0';
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
-- shift register must be 101010101 in the end
shift_en<='0';
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
data_sync<='1';
wait for 1*clk_period;
-- tries adding 11, but shift enable signal is not on, so shift register must
keep its value
output_en<='1'; -- output what is on the shift register
wait for 1*clk_period;
shift_clr<='1'; -- clears the shift register
wait for 1*clk_period;
wait;
end process;
end testbench;
d. Shell
i. code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SCI_Receiver_top is
Port ( clk : in STD_LOGIC;
data_in : in STD_LOGIC; -- 1bit signal from AD2;
done_tick: out STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of
parallel data
end SCI_Receiver_top;
architecture Behavioral of SCI_Receiver_top is
component SCI_receiver_controller IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync: in STD_LOGIC; -- 1bit signal from double flop
synchronizer
shift_en : out STD_LOGIC; -- send to datapath
shift_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
done_tick : out STD_LOGIC); -- indicates new data is ready
end component;
45
component SCI_receiver_datapath IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_sync : in STD_LOGIC; -- 1bit signal from flop
synchronizer
shift_en : in STD_LOGIC; -- receiveing from controller
shift_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of
parallel data
end component;
component SCI_receiver_double_flop IS
PORT ( clk : in STD_LOGIC; --10MHz clock
data_in : in STD_LOGIC; -- 1bit signal from AD2
data_sync : out STD_LOGIC); -- 1bit signal after being delayed
by 2 clk cycles
end component;
signal shift_en,shift_clr,output_en: STD_LOGIC :='0';
signal data_sync: STD_LOGIC :='1';
begin
uut : SCI_receiver_controller
port map ( clk => clk, --10MHz clock
data_sync => data_sync, -- 1bit signal from double flop
synchronizer
shift_en => shift_en, -- send to datapath
shift_clr => shift_clr, -- send to datapath
output_en => output_en, -- send to datapath
done_tick => done_tick); -- indicates new data is ready
uut2: SCI_receiver_datapath
port map ( clk => clk, --10MHz clock
data_sync => data_sync, -- 1bit signal from flop synchronizer
shift_en => shift_en, -- receiveing from controller
shift_clr => shift_clr, -- receiveing from controller
output_en => output_en, -- receiveing from controller
data_out => data_out);-- 8 bits of parallel data
uut3: SCI_receiver_double_flop
port map ( clk => clk, --10MHz clock
data_in => data_in, -- 1bit signal from AD2
data_sync => data_sync); -- 1bit signal after being delayed by 2
clk cycles
end Behavioral;
46
2. SCI Transmitter
a. Double-Flop Synchronizer
i. code
-- Code your design here
library IEEE;
use IEEE.std_logic_1164.all;
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY SCI_transmitter_double_flop IS
PORT ( clk : in STD_LOGIC; --10MHz clock
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit
signal from SCI receiver
receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit
signal after being delayed by 2 clk cycles
end SCI_transmitter_double_flop;
architecture behavior of SCI_transmitter_double_flop is
--Signals
signal dsync : std_logic_vector(7 downto 0) :="00000000"; -- signals for
double flop synchronizer
BEGIN
-- Double-flop synchronizer
double_flop_sync: process (clk)
begin
if rising_edge(clk) then
dsync <= receiver_data; -- flop 1
receiver_data_sync <= dsync; -- flop 2
end if;
end process;
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
entity SCI_transmitter_double_flop_tb is
end SCI_transmitter_double_flop_tb;
architecture testbench of SCI_transmitter_double_flop_tb is
component SCI_transmitter_double_flop
47
PORT ( clk : in STD_LOGIC; --10MHz clock
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit
signal from SCI receiver
receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit
signal after being delayed by 2 clk cycles
end component;
-- signals
signal receiver_data, receiver_data_sync: std_logic_vector(7 downto 0) :=
"00000000";
signal clk : std_logic :='0';
constant clk_period: time := 100ns; --10MHz clock
begin
uut : SCI_transmitter_double_flop PORT MAP(
clk=> clk,
receiver_data=> receiver_data,
receiver_data_sync=> receiver_data_sync);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 1*clk_period;
receiver_data<="11111111";
wait for 1*clk_period;
receiver_data<="10101010";
wait for 1*clk_period;
end process;
end testbench;
b. Controller
i. code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY SCI_transmitter_controller IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
48
data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from flop synchronizer
done_tick : in STD_LOGIC; -- from controller of receiver; indicates
that new 8bit data is ready
load_en : out STD_LOGIC; -- send to datapath
reg_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
end_tick : out STD_LOGIC);-- indicates finished passing the
data to AD2
end SCI_transmitter_controller;
architecture behavior of SCI_transmitter_controller is
--Signals
type state_type is (idle, wait_T, shift_load, shift_nums, clear); -- states
of FSM
signal current_state, next_state : state_type := idle;
signal count_halfT, count_T, count_T_en,end_tick_signal, output_en_signal:
std_logic:= '0';
signal count_shift, count_Tclk_cycles: integer:=0;
BEGIN
-- update state machine states
stateUpdate: process(clk)
BEGIN
if rising_edge(clk) then
current_state <= next_state;
end if;
end process stateUpdate;
-- controller
controller: process (current_state, done_tick, count_shift, count_T)
begin
-- defaults; will only change inside the states
load_en<='0';
reg_clr<='0';
output_en<='0';
end_tick<='0';
count_T_en <='0';
output_en_signal<='0';
case (current_state) is
when idle=>
if done_tick='1' then -- ready to receive new bits
next_state<=shift_load;
end if;
49
when shift_load=>
load_en<='1'; -- data goes to shift register
next_state<=shift_nums;
when shift_nums=>
output_en<='1';-- allows numbers to get shifted out
output_en_signal<='1';
if count_shift = 9 then -- after shifting 10 bits of data
next_state<= clear;
else
next_state<= wait_T;
end if;
when wait_T=>
count_T_en <='1';
if count_T='1' then -- after waited T
next_state<=shift_nums;
end if;
when clear=>
end_tick<='1'; -- indicates that finished shifitng data out
end_tick_signal<='1';
reg_clr<='1'; -- clear register
next_state<=idle;
end case;
end process;
-- count how many bits have been output
bit_count: process (clk, output_en_signal, end_tick_signal)
begin
if rising_edge(clk) then
if output_en_signal='1' then -- in shift state
count_shift<=count_shift+1;
end if;
if end_tick_signal ='1' then -- indicates we have 10 bits of data
count_shift<=0;
end if;
end if;
end process;
-- counter for baud rate
time_T: process (clk, count_T_en)
begin
if rising_edge (clk) then
if count_T_en='1' then
count_Tclk_cycles <= count_Tclk_cycles+1;
if count_Tclk_cycles = 1041 then -- num of clk cycles (1042 clck
cycles) to count for T, based on a 10Mhz clk period
count_T<='1'; -- flags that T has passed; T = 1/9600
50
count_Tclk_cycles <=0; -- resets counter after reaching 1042
clock cycles
else
count_T<='0';
end if;
end if;
end if;
end process;
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity SCI_transmitter_controller_tb is
end SCI_transmitter_controller_tb;
architecture testbench of SCI_transmitter_controller_tb is
component SCI_transmitter_controller
PORT ( clk : in STD_LOGIC; --10 MHz clock
data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from flop synchronizer
done_tick : in STD_LOGIC; -- from controller of receiver; indicates
that new 8bit data is ready
load_en : out STD_LOGIC; -- send to datapath
reg_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
end_tick : out STD_LOGIC);-- indicates finished passing the
data to AD2
end component;
-- signals
signal clk, done_tick, load_en, reg_clr, output_en, end_tick: std_logic :=
'0';
signal data_in_sync: std_logic_vector(7 downto 0):= "00000000";
constant clk_period: time := 100ns; --10 MHz clock
begin
uut : SCI_transmitter_controller PORT MAP(
51
clk => clk,
data_in_sync=> data_in_sync,
done_tick=> done_tick,
load_en=> load_en,
reg_clr=>reg_clr,
output_en=>output_en,
end_tick=>end_tick);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 5*clk_period;
done_tick<='1'; -- receives new data
wait for 1*clk_period;
done_tick<='0';
wait for 1*clk_period;
data_in_sync<="10101010";
wait for 10420*clk_period;
wait for 400*clk_period;
end process;
end testbench;
c. Datapath
i. Code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY SCI_transmitter_datapath IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from flop synchronizer
load_en : in STD_LOGIC; -- receiveing from controller
reg_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
transmitter_data_out : out STD_LOGIC);-- 1 bit signal to AD2
52
end SCI_transmitter_datapath;
architecture behavior of SCI_transmitter_datapath is
--Signals
signal shift_reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10
bits of data
signal fill_reg: std_logic:= '0'; -- used to left shift bits out of the
register
signal start_bit: std_logic:='0'; -- start bit to be added to the signal for
each letter
signal end_bit: std_logic:='1'; -- end bit to be added to the signal for each
letter
BEGIN
-- Shift and output registers
registers: process (clk, output_en, load_en, reg_clr)
begin
if rising_edge(clk) then
if reg_clr ='1' then -- clears what is inside the shift register
shift_reg<="0000000000";
elsif reg_clr ='0' then -- if doesn't want to clear the register
if load_en='1' then -- shift register gets the value of the
data coming in (the 8-bits coming from SCI transmitter and delayed by the
double-flop)
shift_reg <= (start_bit)&(data_in_sync)&(end_bit); -- adds
start and end bit and save value in a shift register
else
shift_reg<= shift_reg; -- shift reg hold its current value
end if;
if output_en ='1' then -- when load register is enabled
transmitter_data_out <= shift_reg(9); -- outputs first bit of
data
shift_reg<= shift_reg(8 downto 0)&fill_reg; -- left shifting
the bits out of the register
end if;
end if;
end if;
end process;
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
53
use IEEE.numeric_std.all;
entity SCI_transmitter_datapath_tb is
end SCI_transmitter_datapath_tb;
architecture testbench of SCI_transmitter_datapath_tb is
component SCI_transmitter_datapath
PORT ( clk : in STD_LOGIC; --10 MHz clock
data_in_sync: in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from SCI receiver
load_en : in STD_LOGIC; -- receiveing from controller
reg_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
data_out : out STD_LOGIC);-- 1 bit signal to AD2
end component;
-- signals
signal clk, data_out, load_en, reg_clr, output_en: std_logic := '0';
signal data_in_sync: std_logic_vector(7 downto 0) := (others=>'0');
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut : SCI_transmitter_datapath PORT MAP(
clk => clk,
data_in_sync=> data_in_sync,
load_en=> load_en,
reg_clr=> reg_clr,
output_en=>output_en,
data_out=>data_out);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
load_en<='1'; -- allows shift register to receive the data
wait for 1*clk_period;
data_in_sync<="11111111";
wait for 1*clk_period;
load_en<='0';
wait for 1*clk_period;
54
reg_clr<='1'; -- clears the shift register
wait for 1*clk_period;
reg_clr<='0';
wait for 1*clk_period;
data_in_sync<="10101010";
wait for 1*clk_period;
load_en<='1'; -- allows shift register to receive the data
wait for 1*clk_period;
-- shift register must be 11001100
load_en<='0'; -- cannot receive data anymore
wait for 1*clk_period;
data_in_sync<="11111111";
wait for 1*clk_period;
-- tries adding new value, but shift enable signal is not on, so shift
register must keep its value
output_en<='1'; -- output what is on the shift register
wait for 8*clk_period;
output_en<='0';
wait for 1*clk_period;
end process;
end testbench;
d. Shell
i. code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SCI_Transmitter_top is
Port ( clk : in STD_LOGIC;
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0);
done_tick: in std_logic;
transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2
end_tick : out STD_LOGIC);-- indicates finished passing the
data to AD2
end SCI_Transmitter_top;
architecture Behavioral of SCI_Transmitter_top is
component SCI_transmitter_controller IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from flop synchronizer
done_tick : in STD_LOGIC; -- from controller of receiver; indicates
that new 8bit data is ready
load_en : out STD_LOGIC; -- send to datapath
reg_clr : out STD_LOGIC; -- send to datapath
output_en : out STD_LOGIC; -- send to datapath
55
end_tick : out STD_LOGIC);-- indicates finished passing the
data to AD2
end component;
component SCI_transmitter_datapath IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal
(parallel data) from flop synchronizer
load_en : in STD_LOGIC; -- receiveing from controller
reg_clr : in STD_LOGIC; -- receiveing from controller
output_en : in STD_LOGIC; -- receiveing from controller
transmitter_data_out : out STD_LOGIC);-- 1 bit signal to AD2
end component;
component SCI_transmitter_double_flop IS
PORT ( clk : in STD_LOGIC; --10MHz clock
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit
signal from SCI receiver
receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit
signal after being delayed by 2 clk cycles
end component;
signal load_en,reg_clr,output_en: STD_LOGIC :='0';
signal data_in_sync,receiver_data_sync :std_logic_vector(7 downto
0):=(others=>'0');
begin
uut4 : SCI_Transmitter_controller
port map( clk=>clk, --10 MHz clock
data_in_sync =>receiver_data, -- 8bit signal (parallel data)
from flop synchronizer
done_tick =>done_tick , -- from controller of receiver; indicates
that new 8bit data is ready
load_en=>load_en, -- send to datapath
reg_clr=>reg_clr, -- send to datapath
output_en=>output_en, -- send to datapath
end_tick =>end_tick);-- indicates finished passing the data to
AD2
uut5: SCI_Transmitter_datapath
port map ( clk => clk, --10 MHz clock
data_in_sync => receiver_data, -- 8bit signal (parallel data)
from flop synchronizer
load_en =>load_en, -- receiveing from controller
reg_clr =>reg_clr, -- receiveing from controller
output_en =>output_en, -- receiveing from controller
transmitter_data_out =>transmitter_data_out);-- 1 bit signal to
AD2
uut3: SCI_Transmitter_double_flop
port map ( clk => clk, --10MHz clock
56
receiver_data =>receiver_data, -- 8bit signal from SCI receiver
receiver_data_sync=>receiver_data_sync); -- 8bit signal after
being delayed by 2 clk cycles
end Behavioral;
ii. testbench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SCI_Transmitter_top_tb is
end SCI_Transmitter_top_tb;
architecture Testbench of SCI_Transmitter_top_tb is
component SCI_Transmitter_top is
Port ( clk : in STD_LOGIC;
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0);
done_tick: in std_logic;
transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2
end_tick : out STD_LOGIC);-- indicates finished passing the
data to AD2
end component;
signal clk : std_logic := '0';
signal transmitter_data_out, done_tick : std_logic:= '0';
signal receiver_data: std_logic_vector(7 downto 0):= (others => '0');
signal end_tick :std_logic :='0';
constant clk_period : time := 100ns; -- 10 MHz clock
-- Data definitions
BEGIN
uut00: SCI_Transmitter_top
port map ( clk => clk,
receiver_data=> receiver_data,-- 1bit signal from AD2;
done_tick=> done_tick,
end_tick => end_tick,
transmitter_data_out => transmitter_data_out);-- 8 bits of
parallel data
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_proc: process
begin
57
done_tick<='1';
receiver_data<="01010100";
wait for 1*clk_period;
done_tick<='0';
wait for 10420*clk_period;
done_tick<='1';
receiver_data<="00000000";
wait for 1*clk_period;
done_tick<='0';
wait for 10420*clk_period;
done_tick<='1';
receiver_data<="10010001";
wait for 1*clk_period;
done_tick<='0';
wait for 10420*clk_period;
wait for 400*clk_period;
end process;
end Testbench;
3. Check Character
i. code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY check_character IS
PORT ( clk : in STD_LOGIC; --2MHz master clock
Data_in_receiver : in STD_LOGIC_VECTOR(7 downto
0); --from sci receiver
read_en : out std_logic);
end check_character;
architecture behaviour of check_character is
begin
process(clk)
BEGIN
read_en<='0';
if rising_edge(clk) then
if Data_in_receiver="00001010" then --ascii code of enter
read_en<='1';
else
read_en<='0';
end if ;
58
end if;
end process;
end behaviour;
ii. testbench
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity check_character_tb is
end check_character_tb ;
architecture testbench of check_character_tb is
component check_character is
PORT (clk : in STD_LOGIC; --10MHz master clock
Data_in_receiver : in STD_LOGIC_VECTOR(7 downto
0);
read_en : out std_logic);
end component;
signal clk: std_logic;
signal Data_in_receiver : std_logic_vector(7 downto 0):="00000000" ;
signal read_en : std_logic := '0';
begin
uut : check_character PORT MAP(
clk => clk,
Data_in_receiver => Data_in_receiver,
read_en => read_en);
clk_proc : process
BEGIN
CLK <= '0';
wait for 5ns;
CLK <= '1';
wait for 5ns;
end process clk_proc;
stim_proc : process
begin
Data_in_receiver <= "11110000";
wait for 8 ns;
Data_in_receiver <= "00001111";
wait for 8 ns;
59
Data_in_receiver <= "10101010";
wait for 8 ns;
Data_in_receiver <="00001010";
wait for 8 ns;
Data_in_receiver <= "01010101";
wait for 8 ns;
Data_in_receiver <= "11110000";
wait for 8 ns;
Data_in_receiver <= "00001111";
wait for 8 ns;
Data_in_receiver <= "10101010";
wait for 8 ns;
Data_in_receiver <="00101010";
wait for 8 ns;
Data_in_receiver <= "01010101";
wait for 8 ns;
end process stim_proc;
end testbench;
4. Buffer
i. code
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY Queue IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
Write_en : in STD_LOGIC; --input character
read_en : in STD_LOGIC; --enter pressed
done_translating: in std_logic; --Done translating a character
to input a new one
Data_in_Q : in STD_LOGIC_VECTOR(7 downto 0);
Data_out_Q: out STD_LOGIC_VECTOR(7 downto 0);
full: out std_logic);
end Queue;
architecture behavior of Queue is
60
type regfile is array(0 to 100) of STD_LOGIC_VECTOR(7 downto 0);
signal Queue_reg : regfile;
signal W_ADDR : integer := 0;
signal R_ADDR : integer := 0;
signal used,count: integer := 0;
signal full_sig : std_logic;
constant threshold: integer := 101;
BEGIN
process(clk,write_en,read_en,data_in_Q,done_translating)
begin
if rising_edge(clk) then
if (Write_en = '1') and read_en='0' then --if a new character
is inputted
if (full_sig = '0') then --if the queue is not full
Queue_reg(W_ADDR) <= Data_in_Q; --stores data in the
queue
used<=used+1;
count<=count+1;
if W_ADDR =threshold-1 then --if the queue is full and we
can no longer write, reset the address back to zero
W_ADDR <= 0;
used<=0;
count<=0;
else
W_ADDR <= W_ADDR + 1; --otherwise, increment the address
to store data in the queue
end if;
end if;
end if;
if (read_en = '1') then -- if enter is pressed
if done_translating='1' then --and if the previous
charcter is already transalted by the interpreter to its morse code
Queue_reg(R_ADDR) <= (others => '0'); --after it
reads whatever is in the address, it resets it back to zero
used<=used-1; -- and decrement the number of used
levels by one
if R_ADDR = threshold-1 then
R_ADDR <= 0;
used<=0;
else
R_ADDR <= R_ADDR + 1;
end if;
end if;
end if;
end if;
61
Data_out_Q <= Queue_reg(R_ADDR); --the queue is reading the stored
data and outputting it
end process;
full_proc: process(count,clk)
begin
if rising_edge(clk) then
if count=threshold-1 then --if the number of used levels is equal to
the full size of the queue
full_sig<='1'; --full signal becomes high
else full_sig<='0';
end if;
end if;
end process;
full <= full_sig; --the signal will light up an LED to tell the user
that the queue is full
end behavior;
ii. testbench
library IEEE;
use IEEE.std_logic_1164.all;
entity Queue_tb is
end Queue_tb;
architecture testbench of Queue_tb is
component Queue IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
Write_en : in STD_LOGIC;
read_en : in STD_LOGIC;
done_translating : in STD_LOGIC;
Data_in : in STD_LOGIC_VECTOR(7 downto 0);
full: out std_logic;
Data_out: out STD_LOGIC_VECTOR(7 downto 0));
end component;
signal clk : STD_LOGIC; --10 MHz clock
signal Write_en : STD_LOGIC := '0';
signal Read_en : STD_LOGIC := '0';
signal done_translating: STD_LOGIC := '0';
signal full : std_logic :='0';
signal Data_in : STD_LOGIC_Vector(7 downto 0) :=
"00000000";
signal Data_out: STD_LOGIC_Vector(7 downto 0) := "00000000";
62
begin
uut : Queue PORT MAP(
clk => CLK,
Read_en => Read_en,
Write_en => Write_en,
Data_in => Data_in,
full => full,
done_translating=>done_translating,
Data_out => Data_out);
clk_proc : process
BEGIN
CLK <= '0';
wait for 5ns;
CLK <= '1';
wait for 5ns;
END PROCESS clk_proc;
stim_proc : process
begin
write_en<= '0';
read_en<= '0';
wait for 8 ns;
write_en<='1';
wait for 30 ns;
Data_in <= "00000000";
wait for 5 ns;
Data_in <= "00000001";
wait for 5 ns;
Data_in <= "00000010";
wait for 5 ns;
Data_in <= "00000100";
wait for 5 ns;
Data_in<= "00001000";
wait for 5 ns;
Data_in <= "00010000";
63
wait for 10 ns;
write_en<='0';
wait for 5 ns;
read_en<='1';
done_translating<='1';
wait for 15 ns;
write_en<='1';
wait for 8 ns;
Data_in <= "10000000";
wait for 5 ns;
Data_in <= "11000000";
wait for 5 ns;
Data_in <= "11100000";
wait for 5 ns;
Data_in <= "11110000";
wait for 5 ns;
Data_in<= "11111000";
wait for 5 ns;
Data_in<= "11111100";
wait for 5 ns;
Data_in<= "11111110";
wait for 5 ns;
done_translating<='1';
wait for 8 ns;
Data_in<= "11111110";
wait for 8 ns;
Data_in<= "11111111";
wait for 8 ns;
wait;
end process stim_proc;
end testbench;
5. Morse Translator
i. code
64
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY translator IS
PORT ( clk : in STD_LOGIC; --10MHz master clock
Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0);
--from buffer
done : out STD_LOGIC;
Morse_code: out STD_LOGIC_VECTOR(9 downto 0));
end translator;
architecture behaviour of translator is
BEGIN
process(Data_out_buffer)
begin
done<= '0';
case Data_out_buffer is
when "01000001" => Morse_code <= "0111000000"; --A
done<='1';
when "01000010" => Morse_code <= "1101010100"; --B
done<='1';
when "01000011" => Morse_code <= "1101110100"; --C
done<='1';
when "01000100" => Morse_code <= "1101010000"; --D
done<='1';
when "01000101" => Morse_code <= "0100000000"; --E
done<='1';
when "01000110" => Morse_code <= "0101110100"; --F
done<='1';
when "01000111" => Morse_code <= "1111010000"; --G
done<='1';
when "01001000" => Morse_code <= "0101010100"; --H
done<='1';
when "01001001" => Morse_code <= "0101000000"; --I
done<='1';
when "01001010" => Morse_code <= "0111111100"; --J
done<='1';
when "01001011" => Morse_code <= "1101110000"; --K
done<='1';
when "01001100" => Morse_code <= "0111010100"; --L
done<='1';
when "01001101" => Morse_code <= "1111000000"; --M
done<='1';
when "01001110" => Morse_code <= "1101000000"; --N
done<='1';
when "01001111" => Morse_code <= "1111110000"; --O
done<='1';
when "01010000" => Morse_code <= "0111110100"; --P
done<='1';
65
when "01010001" => Morse_code <= "1111011100"; --Q
done<='1';
when "01010010" => Morse_code <= "0111010000"; --R
done<='1';
when "01010011" => Morse_code <= "0101010000"; --S
done<='1';
when "01010100" => Morse_code <= "1100000000"; --T
done<='1';
when "01010101" => Morse_code <= "0101110000"; --U
done<='1';
when "01010110" => Morse_code <= "0101011100"; --V
done<='1';
when "01010111" => Morse_code <= "0111110000"; --W
done<='1';
when "01011000" => Morse_code <= "1101011100"; --X
done<='1';
when "01011001" => Morse_code <= "1101111100"; --Y
done<='1';
when "01011010" => Morse_code <= "1111010100"; --Z
done<='1';
when "00000000" => Morse_code <= "1111111111"; --0
done<='1';
when "00000001" => Morse_code <= "0111111111"; --1
done<='1';
when "00000010" => Morse_code <= "0101111111"; --2
done<='1';
when "00000011" => Morse_code <= "0101011111"; --3
done<='1';
when "00000100" => Morse_code <= "0101010111"; --4
done<='1';
when "00000101" => Morse_code <= "0101010101"; --5
done<='1';
when "00000110" => Morse_code <= "1101010101"; --6
done<='1';
when "00000111" => Morse_code <= "1111010101"; --7
done<='1';
when "00001000" => Morse_code <= "1111110101"; --8
done<='1';
when "00001001" => Morse_code <= "1111111101"; --9
done<='1';
when "00100000" => Morse_code <= "0000000000"; --space
done<='1';
when "01100001" => Morse_code <= "0111000000"; --a
done<='1';
when "01100010" => Morse_code <= "1101010100"; --b
done<='1';
when "01100011" => Morse_code <= "1101110100"; --c
done<='1';
when "01100100" => Morse_code <= "1101010000"; --d
done<='1';
when "01100101" => Morse_code <= "0100000000"; --e
66
done<='1';
when "01100110" => Morse_code <= "0101110100"; --f
done<='1';
when "01100111" => Morse_code <= "1111010000"; --g
done<='1';
when "01101000" => Morse_code <= "0101010100"; --h
done<='1';
when "01101001" => Morse_code <= "0101000000"; --i
done<='1';
when "01101010" => Morse_code <= "0111111100"; --j
done<='1';
when "01101011" => Morse_code <= "1101110000"; --k
done<='1';
when "01101100" => Morse_code <= "0111010100"; --l
done<='1';
when "01101101" => Morse_code <= "1111000000"; --m
done<='1';
when "01101110" => Morse_code <= "1101000000"; --n
done<='1';
when "01101111" => Morse_code <= "1111110000"; --o
done<='1';
when "01110000" => Morse_code <= "0111110100"; --p
done<='1';
when "01110001" => Morse_code <= "1111011100"; --q
done<='1';
when "01110010" => Morse_code <= "0111010000"; --r
done<='1';
when "01110011" => Morse_code <= "0101010000"; --s
done<='1';
when "01110100" => Morse_code <= "1100000000"; --t
done<='1';
when "01110101" => Morse_code <= "0101110000"; --u
done<='1';
when "01110110" => Morse_code <= "0101011100"; --v
done<='1';
when "01110111" => Morse_code <= "0111110000"; --w
done<='1';
when "01111000" => Morse_code <= "1101011100"; --x
done<='1';
when "01111001" => Morse_code <= "1101111100"; --y
done<='1';
when "01111010" => Morse_code <= "1111010100"; --z
done<='1';
when others => Morse_code <= "1111111111"; --in case of an
invalid input, the output will be a zero
done<='1';
end case;
end process;
end behaviour;
67
ii. testbench
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity translator_tb is
end translator_tb ;
architecture testbench of translator_tb is
component translator is
PORT ( clk : in STD_LOGIC; --2MHz master clock
Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0);
--from buffer
done : out STD_LOGIC;
Morse_code: out STD_LOGIC_VECTOR(9 downto 0));
end component;
signal clk: std_logic;
signal Data_out_buffer: std_logic_vector(7 downto 0) :="00000000";
signal done: std_logic :='0';
signal Morse_code: std_logic_vector(9 downto 0) :="0000000000";
begin
uut : translator PORT MAP(
clk => clk,
data_out_buffer => data_out_buffer,
Morse_code => Morse_code,
done =>done);
clk_proc : process
BEGIN
CLK <= '0';
wait for 5ns;
CLK <= '1';
wait for 5ns;
end process clk_proc;
stim_proc : process
begin
Data_out_buffer<="01001000";
wait for 20 ns;
Data_out_buffer<="01100101";
wait for 20 ns;
Data_out_buffer<="01101100";
wait for 20 ns;
68
Data_out_buffer<="01101100";
wait for 20 ns;
Data_out_buffer<="01001111";
wait for 20 ns;
Data_out_buffer<="10101010"; --random number
wait for 20 ns;
wait;
end process stim_proc;
end testbench;
6. Morse Interpreter
a. Controller
i. code
-- Code your design here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY morse_interpreter_controller IS
PORT ( clk : in STD_LOGIC; -- 10 MHz clk
translation_done : in STD_LOGIC; -- indicates new character is ready
space: in STD_LOGIC; -- from datapath
not_space: in STD_LOGIC; -- from datapath
dot: in STD_LOGIC; -- from datapath
dash: in STD_LOGIC; -- from datapath
end_char: in STD_LOGIC; -- from datapath
load_en : out STD_LOGIC; -- send to datapath
shift_en : out STD_LOGIC; -- send to datapath
check_bits_en: out STD_LOGIC; -- send to datapath
count_T_en: out STD_LOGIC; -- send to datapath
count_3T_en: out STD_LOGIC; -- send to datapath
count_7T_en: out STD_LOGIC; -- send to datapath
end_trans : out STD_LOGIC);-- indicates the translation is
over
end morse_interpreter_controller;
architecture behavior of morse_interpreter_controller is
--Signals
type state_type is (idle, shift_register, shift_bits, check_bits, clear,
time_3T, time_T, time_7T, time_within_letter, time_between_letters); --
states of FSM
69
signal current_state, next_state : state_type := idle;
signal count_7T, count_3T, count_T, count_within_char, count_between_letters:
integer:=0; -- count the time between works and characters
signal count_between_letters_TC, count_T_TC, count_3T_TC, count_7T_TC,
count_within_char_TC: std_logic:='0';
signal count_3T_en_signal, count_T_en_signal, count_7T_en_signal,
count_within_char_en, count_between_letters_en : std_logic:='0';
BEGIN
-- update state machine states
stateUpdate: process(clk)
BEGIN
if rising_edge(clk) then
current_state <= next_state;
end if;
end process stateUpdate;
-- CONTROLLER
controller: process (current_state, translation_done, space, not_space, dot,
dash, end_char, count_3T_TC, count_T_TC,
count_7T_TC,count_T,count_within_char_TC, count_between_letters_TC)
begin
-- defaults; will only change inside the states
count_T_en_signal<='0';
count_3T_en_signal<='0';
count_7T_en_signal<='0';
count_within_char_en<='0';
count_between_letters_en<='0';
load_en<='0';
shift_en<='0';
check_bits_en<='0';
count_3T_en<='0';
count_7T_en<='0';
count_T_en<='0';
end_trans<='0';
case (current_state) is
when idle=>
if translation_done='1' then -- ready to receive new bits
next_state<=shift_register;
end if;
when shift_register=>
load_en<='1'; -- enables to load data into a register
if space='1' then -- if the character is a space
next_state<=time_7T; -- waits for 7T
elsif not_space='1' then
next_state<=check_bits; --waits for 3T
end if;
70
when time_between_letters=>
count_between_letters_en<='1';
if count_between_letters_TC = '1' then -- after waited 3T
next_state<= clear;
end if;
when shift_bits=>
shift_en<='1'; -- enables to left shift the bits
next_state<= check_bits;
when check_bits=>
check_bits_en<='1';
if dot='1' then
next_state<= time_T; -- dot
elsif dash='1' then
next_state<= time_3T; -- dash
end if;
if end_char='1' then
next_state<= time_between_letters; -- end of chacracter
end if;
when time_within_letter=> -- time between dots and dashes
count_within_char_en<='1';
if count_within_char_TC = '1' then -- after waited T (1000000)
next_state<= shift_bits;
end if;
when time_3T=>
count_3T_en<='1';
count_3T_en_signal<='1';
if count_3T_TC = '1' then -- after waited 3T (3000000)
next_state<= time_within_letter;
end if;
when time_T=>
count_T_en<='1';
count_T_en_signal<='1';
if count_T_TC = '1' then -- after waited T (1000000)
next_state<= time_within_letter;
end if;
when time_7T=>
count_7T_en<='1';
count_7T_en_signal<='1';
if count_7T_TC = '1' then -- after waited 7T (7000000)
next_state<= clear;
end if;
when clear=>
71
end_trans<='1';
next_state<=idle;
when others=> -- deals with other cases
next_state<=idle;
end case;
end process;
-- WAITING TIME FOR MORSE CODE
time_within_char: process(clk, count_within_char_en)
begin
if rising_edge(clk) then
if count_within_char_en = '1' then
count_within_char<= count_within_char+1;
if count_within_char= 999999 then
count_within_char_TC<='1';
else
count_within_char_TC<='0';
end if;
else
count_within_char <= 0; -- zero the counter
end if;
end if;
end process;
time_Between_two_letters: process(clk, count_between_letters_en)
begin
if rising_edge(clk) then
if count_between_letters_en = '1' then
count_between_letters<= count_between_letters+1;
if count_between_letters= 999999 then
count_between_letters_TC<='1';
else
count_between_letters_TC<='0';
end if;
else
count_between_letters <= 0; -- zero the counter
end if;
end if;
end process;
wait_time_T: process (clk, count_T_en_signal)
begin
if rising_edge(clk) then
if count_T_en_signal='1' then -- in time_T state
count_T<=count_T+1;
if count_T = 999999 then
count_T_TC <= '1';
else
72
count_T_TC<='0';
end if;
end if;
if count_T_en_signal ='0' then -- zero the counter
count_T<=0;
end if;
end if;
end process;
wait_time_3T: process (clk, count_3T_en_signal)
begin
if rising_edge(clk) then
if count_3T_en_signal='1' then -- in time_3T state
count_3T<=count_3T+1;
if count_3T = 2999999 then
count_3T_TC <= '1';
else
count_3T_TC<='0';
end if;
end if;
if count_3T_en_signal ='0' then -- zero the counter
count_3T<=0;
end if;
end if;
end process;
wait_time_7T: process (clk, count_7T_en_signal)
begin
if rising_edge(clk) then
if count_7T_en_signal='1' then -- in time_7T state
count_7T<=count_7T+1;
if count_7T = 5999999 then
count_7T_TC <= '1';
else
count_7T_TC<='0';
end if;
end if;
if count_7T_en_signal='0' then -- zero the counter
count_7T<=0;
end if;
end if;
end process;
end behavior;
ii. testbench
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
73
entity morse_interpreter_controller_tb is
end morse_interpreter_controller_tb;
architecture testbench of morse_interpreter_controller_tb is
component morse_interpreter_controller
PORT ( clk : in STD_LOGIC; -- 10 MHz clk
translation_done : in STD_LOGIC; -- indicates new character is ready
space: in STD_LOGIC; -- from datapath
not_space: in STD_LOGIC; -- from datapath
dot: in STD_LOGIC; -- from datapath
dash: in STD_LOGIC; -- from datapath
end_char: in STD_LOGIC; -- from datapath
load_en : out STD_LOGIC; -- send to datapath
shift_en : out STD_LOGIC; -- send to datapath
check_bits_en: out STD_LOGIC; -- send to datapath
count_T_en: out STD_LOGIC; -- send to datapath
count_3T_en: out STD_LOGIC; -- send to datapath
count_7T_en: out STD_LOGIC; -- send to datapath
end_trans : out STD_LOGIC);-- indicates the translation is
over
-- signals
end component;
signal clk, dot, dash, end_char, translation_done, space, not_space, load_en,
shift_en, check_bits_en, end_trans,count_T_en,count_3T_en,count_7T_en:
std_logic := '0';
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut : morse_interpreter_controller PORT MAP(
clk => clk,
translation_done=> translation_done,
space=> space,
not_space=>not_space,
dot=> dot,
dash=> dash,
end_char=>end_char,
load_en=>load_en,
shift_en=>shift_en,
check_bits_en=>check_bits_en,
count_T_en=> count_T_en,
count_3T_en=>count_3T_en,
count_7T_en=> count_7T_en,
end_trans=>end_trans);
74
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
-- testing for space case
wait for 5*clk_period;
translation_done<= '1'; -- ready to receive new character
wait for 1*clk_period;
translation_done<= '0';
wait for 1*clk_period;
space<='1';
wait for 70*clk_period;
space<='0';
wait for 70*clk_period;
-- testing for other characters
wait for 5*clk_period;
translation_done<= '1'; -- ready to receive new character
wait for 1*clk_period;
translation_done<= '0';
wait for 1*clk_period;
not_space<='1';
wait for 30*clk_period;
not_space<='0';
dot<='1';
wait for 10*clk_period;
dot<='0';
wait for 10*clk_period;
dash<='1';
wait for 30*clk_period;
dash<='0';
wait for 10*clk_period;
end_char<='1';
wait for 50*clk_period;
end_char<='0';
wait for 1*clk_period;
end process;
end testbench;
b. Datapath
i. Code
-- Code your design here
library IEEE;
75
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY morse_interpreter_datapath IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
translation_done: in std_logic; -- coming from translator;
indicates a new character was converted to morse code
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit
signal encoding morse signal
count_T_en : in STD_LOGIC; -- from controller
count_3T_en : in STD_LOGIC; -- from controller
count_7T_en : in STD_LOGIC; -- from controller
load_en : in STD_LOGIC; -- from controller
shift_en : in STD_LOGIC; -- from controller
check_bits_en : in STD_LOGIC; -- from controller
space : out STD_LOGIC; -- send to controlller
no_space : out STD_LOGIC; -- send to controlller
dot : out STD_LOGIC; -- send to controlller
dash : out STD_LOGIC; -- send to controlller
end_char : out STD_LOGIC; -- send to controlller
sound : out STD_LOGIC;
light : out STD_LOGIC);
end morse_interpreter_datapath;
architecture behavior of morse_interpreter_datapath is
-- signal
signal reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10 bits of
data
signal fill_reg: std_logic_vector(1 downto 0):= "00"; -- used to left shift
bits out of the register
BEGIN
-- DATAPATH
translation: process (clk, translation_done, load_en, morse_in, shift_en,
check_bits_en)
begin
if rising_edge(clk) then
--if translation_done = '1' then -- gets new morse code
if load_en='1' then -- enables morse code to be saved in the
register
reg<= morse_in; -- register gets the morse code value
if morse_in = "0000000000" then -- if the character is a space
space<='1'; -- flags we received a space
no_space<='0';
else
no_space<='1'; -- flags we have a regular character
space<='0';
end if;
76
else
space<='0';
no_space<='0';
reg<=reg; -- register gets its current value
end if;
if shift_en='1' then
reg<= reg(7 downto 0)&fill_reg; -- left shifting the bits out
of the register
end if;
if check_bits_en='1' then
if reg(9 downto 8)="01" then
dot<='1'; -- flags we have a dot
dash<='0';
end_char<='0';
elsif reg(9 downto 8)="11" then
dash<='1'; -- flags we have a dash
dot<='0';
end_char<='0';
elsif reg(9 downto 8)="00" then
end_char<='1'; -- flags we reached end othe character
dash<='0';
dot<='0';
end if;
else
dot<='0';
dash<='0';
end_char<='0';
end if;
if count_T_en='1' then -- during the time for morse code
sound <='1';
light <='1';
elsif count_3T_en='1' then -- during the time for morse code
sound <='1';
light <='1';
elsif count_7T_en ='1' then -- during the time for morse code
sound <='1';
light <='1';
else
sound <='0';
light <='0';
end if;
--end if;
end if;
end process;
77
end behavior;
ii. testbench
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity morse_interpreter_datapath_tb is
end morse_interpreter_datapath_tb;
architecture testbench of morse_interpreter_datapath_tb is
component morse_interpreter_datapath
PORT ( clk : in STD_LOGIC; --10 MHz clock
translation_done: in std_logic; -- coming from translator;
indicates a new character was converted to morse code
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit
signal encoding morse signal
count_T_en : in STD_LOGIC; -- from controller
count_3T_en : in STD_LOGIC; -- from controller
count_7T_en : in STD_LOGIC; -- from controller
load_en : in STD_LOGIC; -- from controller
shift_en : in STD_LOGIC; -- from controller
check_bits_en : in STD_LOGIC; -- from controller
space : out STD_LOGIC; -- send to controlller
no_space : out STD_LOGIC; -- send to controlller
dot : out STD_LOGIC; -- send to controlller
dash : out STD_LOGIC; -- send to controlller
end_char : out STD_LOGIC; -- send to controlller
sound : out STD_LOGIC;
light : out STD_LOGIC);
end component;
-- signals
signal clk, check_bits_en, load_en, shift_en, translation_done, count_T_en,
count_3T_en, count_7T_en, space, no_space, dot, dash, end_char, sound, light
: std_logic := '0';
signal morse_in : std_logic_vector(9 downto 0):= "0000000000";
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut : morse_interpreter_datapath PORT MAP(
clk => clk,
translation_done=>translation_done,
78
morse_in=> morse_in,
count_T_en=>count_T_en,
count_3T_en=>count_3T_en,
count_7T_en=>count_7T_en,
space=>space,
load_en=>load_en,
check_bits_en=> check_bits_en,
shift_en=>shift_en,
no_space=>no_space,
dot=>dot,
dash=>dash,
end_char=>end_char,
sound=>sound,
light=>light);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 1*clk_period;
morse_in<="0111010000"; -- 'S' character
wait for 1*clk_period;
load_en<='1'; -- passes morse code into register
wait for 1*clk_period;
load_en<='0';
wait for 1*clk_period;
check_bits_en<='1'; -- check the first 2 bits
wait for 1*clk_period;
check_bits_en<='0';
wait for 1*clk_period;
shift_en<='1'; -- shifts register to left
wait for 1*clk_period;
shift_en<='0';
wait for 1*clk_period;
check_bits_en<='1'; -- check the next 2 bits
wait for 1*clk_period;
check_bits_en<='0';
wait for 1*clk_period;
count_T_en<='1';
wait for 2*clk_period;
79
count_T_en<='0';
wait for 1*clk_period;
count_3T_en<='1';
wait for 2*clk_period;
count_3T_en<='0';
wait for 1*clk_period;
count_7T_en<='1';
wait for 2*clk_period;
count_7T_en<='0';
wait for 1*clk_period;
translation_done<='0';
wait for 1*clk_period;
morse_in<="0000000000"; -- space character
load_en<='1'; -- passes morse code into register
wait for 1*clk_period;
load_en<='0';
wait for 1*clk_period;
end process;
end testbench;
c. Shell
i. code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity morse_interpreter_top is
Port ( clk : in STD_LOGIC; -- 10 MHz clk
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding
morse signal
translation_done : in STD_LOGIC; -- indicates new character is ready
end_trans: out STD_LOGIC; -- indicates that finished translating one
character
sound: out STD_LOGIC;
light: out STD_LOGIC);
end morse_interpreter_top;
architecture Behavioral of morse_interpreter_top is
80
component morse_interpreter_controller IS
PORT ( clk : in STD_LOGIC; -- 10 MHz clk
translation_done : in STD_LOGIC; -- indicates new character is ready
space: in STD_LOGIC; -- from datapath
not_space: in STD_LOGIC; -- from datapath
dot: in STD_LOGIC; -- from datapath
dash: in STD_LOGIC; -- from datapath
end_char: in STD_LOGIC; -- from datapath
load_en : out STD_LOGIC; -- send to datapath
shift_en : out STD_LOGIC; -- send to datapath
check_bits_en: out STD_LOGIC; -- send to datapath
count_T_en: out STD_LOGIC; -- send to datapath
count_3T_en: out STD_LOGIC; -- send to datapath
count_7T_en: out STD_LOGIC; -- send to datapath
end_trans : out STD_LOGIC);-- indicates the translation is
over
end component;
component morse_interpreter_datapath IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
translation_done: in std_logic; -- coming from translator;
indicates a new character was converted to morse code
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit
signal encoding morse signal
count_T_en : in STD_LOGIC; -- from controller
count_3T_en : in STD_LOGIC; -- from controller
count_7T_en : in STD_LOGIC; -- from controller
load_en : in STD_LOGIC; -- from controller
shift_en : in STD_LOGIC; -- from controller
check_bits_en : in STD_LOGIC; -- from controller
space : out STD_LOGIC; -- send to controlller
no_space : out STD_LOGIC; -- send to controlller
dot : out STD_LOGIC; -- send to controlller
dash : out STD_LOGIC; -- send to controlller
end_char : out STD_LOGIC; -- send to controlller
sound : out STD_LOGIC;
light : out STD_LOGIC);
end component;
signal space,not_space,dot, dash, end_char, load_en, shift_en, check_bits_en,
count_T_en, count_3T_en, count_7T_en, no_space: STD_LOGIC :='0';
begin
uut_inter : morse_interpreter_controller
port map (clk => clk,
translation_done=> translation_done,
space=> space,
not_space=>not_space,
dot=> dot,
81
dash=> dash,
end_char=>end_char,
load_en=>load_en,
shift_en=>shift_en,
check_bits_en=>check_bits_en,
count_T_en=> count_T_en,
count_3T_en=>count_3T_en,
count_7T_en=> count_7T_en,
end_trans=>end_trans);
uut2_inter: morse_interpreter_datapath
PORT MAP( clk => clk,
translation_done => translation_done,
morse_in=> morse_in,
count_T_en=>count_T_en,
count_3T_en=>count_3T_en,
count_7T_en=>count_7T_en,
space=>space,
load_en=>load_en,
check_bits_en=> check_bits_en,
shift_en=>shift_en,
no_space=>not_space,
dot=>dot,
dash=>dash,
end_char=>end_char,
sound=>sound,
light=>light);
end Behavioral;
ii. testbench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity morse_interpreter_top_tb is
end morse_interpreter_top_tb;
architecture Testbench of morse_interpreter_top_tb is
component morse_interpreter_top is
Port ( clk : in STD_LOGIC; -- 10 MHz clk
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding
morse signal
translation_done : in STD_LOGIC; -- indicates new character is ready
82
end_trans: out STD_LOGIC; -- indicates that finished translating one
character
sound: out STD_LOGIC;
light: out STD_LOGIC);
end component;
signal clk : std_logic := '0';
signal translation_done : std_logic:= '0';
signal morse_in: std_logic_vector(9 downto 0):= (others => '0');
signal end_trans, sound, light :std_logic :='0';
constant clk_period : time := 100ns; -- 10 MHz clock
begin
uut0_inter_top: morse_interpreter_top
port map ( clk => clk,
morse_in=> morse_in,
translation_done=> translation_done,
end_trans => end_trans,
sound=> sound,
light => light);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_proc: process
begin
wait for 5*clk_period;
morse_in<="0111000000";
translation_done <='1';
wait for 1*clk_period;
translation_done <='0';
wait for 15000000*clk_period;
morse_in<="0000000000";
translation_done <='1';
wait for 1*clk_period;
translation_done <='0';
wait for 8000000*clk_period;
wait for 1042*clk_period;
end process;
end Testbench;
83
7. Square Wave Oscillator
a. Code:
-- Code your design here
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY square_wave_oscillator IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
sound_wave : out STD_LOGIC);-- square wave at 500Hz
end square_wave_oscillator;
architecture behavior of square_wave_oscillator is
signal counter, counter_high : integer:=0;
signal rate : integer:=999; -- for squarewave at 500Hz (10^6/500)
signal twice_rate : integer:=4000;
signal initial_sound : std_logic:='0';
begin
square_wave: process (clk)
begin
if rising_edge(clk) then
counter<= counter+1;
if (counter=rate) then
initial_sound<= NOT(initial_sound);
counter<=0; -- zeros the counter
end if;
end if;
end process;
sound_wave<=initial_sound;
end behavior;
b. Testbench:
-- Code your testbench here
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity square_wave_oscillator_tb is
end square_wave_oscillator_tb;
architecture testbench of square_wave_oscillator_tb is
84
component square_wave_oscillator
PORT ( clk : in STD_LOGIC; --10 MHz clock
sound_wave : out STD_LOGIC);-- square wave at 500Hz
end component;
signal clk, sound_wave: std_logic := '0';
constant clk_period: time := 100ns; -- 10MHz clock
begin
uut_square : square_wave_oscillator PORT MAP(
clk => clk,
sound_wave=>sound_wave);
clkgen_proc: process
begin
clk <= not(clk);
wait for clk_period/2;
end process clkgen_proc;
stimulus_proc: process
begin
wait for 1000* clk_period;
end process;
end testbench;
8. Final MUX
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity final_mux is
Port ( sound_wave: in std_logic; --from sound oscillator
sound: in std_logic; --from interpreter
sound_final: out STD_LOGIC);
end final_mux;
architecture Behavioral of final_mux is
begin
wave: process (sound,sound_wave)
begin
if sound ='1' then
if sound_wave='1' then
sound_final<='1';
else
85
sound_final<='0';
end if;
end if;
end process;
end Behavioral;
9. Final Top Code (Shell File)
i. code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity final_top is
port (clk : in STD_LOGIC;
data_in : in STD_LOGIC; -- 1bit signal from AD2;
sound_final: out STD_LOGIC;
end_tick : out STD_LOGIC;
Full: out STD_LOGIC;
transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2
light: out STD_LOGIC);
end final_top;
architecture Behavioral of final_top is
component SCI_Receiver_top is
Port ( clk : in STD_LOGIC;
data_in : in STD_LOGIC; -- 1bit signal from AD2;
done_tick: out STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits
of parallel data
end component;
component SCI_Transmitter_top is
Port ( clk : in STD_LOGIC;
receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0);
done_tick: in std_logic;
transmitter_data_out : out STD_LOGIC;-- 1 bit signal
to AD2
end_tick : out STD_LOGIC);-- indicates finished passing
the data to AD2
end component;
component morse_interpreter_top is
Port ( clk : in STD_LOGIC; -- 10 MHz clk
morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal
encoding morse signal
86
translation_done : in STD_LOGIC; -- indicates new character is
ready
end_trans: out STD_LOGIC; -- indicates that finished
translating one character
sound: out STD_LOGIC;
light: out STD_LOGIC);
end component;
component Queue IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
Write_en : in STD_LOGIC; --input character
read_en : in STD_LOGIC; --enter pressed
done_translating: in std_logic;
Data_in_Q : in STD_LOGIC_VECTOR(7 downto 0);
Data_out_Q: out STD_LOGIC_VECTOR(7 downto 0);
full: out std_logic);
end component;
component check_character IS
PORT ( clk : in STD_LOGIC; --2MHz master clock
Data_in_receiver : in STD_LOGIC_VECTOR(7 downto
0); --from sci receiver
read_en : out std_logic);
end component;
component square_wave_oscillator IS
PORT ( clk : in STD_LOGIC; --10 MHz clock
sound_wave : out STD_LOGIC);-- square wave at 500Hz
end component;
component translator IS
PORT ( clk : in STD_LOGIC; --10MHz master clock
Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0);
--from buffer
done : out STD_LOGIC;
Morse_code: out STD_LOGIC_VECTOR(9 downto 0));
end component;
component final_mux is
Port ( sound_wave: in std_logic; --from sound oscillator
sound: in std_logic; --from interpreter
sound_final: out STD_LOGIC);
end component;
signal
done,sound_wave,full,read_en,done_translating,write_en,done_tick,transl
ation_done,end_trans,sound : STD_LOGIC; -- 1bit signal from AD2;
signal data_out_buffer,data_out,
receiver_data,data_in_Q,data_out_Q,data_in_receiver :
STD_LOGIC_VECTOR(7 downto 0);
87
signal morse_in,morse_code : STD_LOGIC_VECTOR(9 downto 0); -- 10 bit
signal encoding morse signal
begin
uutf1 : SCI_Receiver_top
port map(clk =>clk,
data_in => data_in,
done_tick=>done_tick,
data_out =>data_out);-- 8 bits of parallel data
uutf2: SCI_Transmitter_top
Port map ( clk =>clk,
receiver_data =>data_out,
done_tick=>done_tick,
transmitter_data_out =>transmitter_data_out,-- 1 bit signal to
AD2
end_tick => end_tick);-- indicates finished passing the data
to AD2
uutf3: check_character
Port map ( clk =>clk, --2MHz master clock
Data_in_receiver=> data_out, --from sci receiver
read_en => read_en);
uutf4: Queue
Port map ( clk => clk, --10 MHz clock
Write_en=> done_tick, --input character
read_en =>read_en, --enter pressed
done_translating =>end_trans,
Data_in_Q=>data_out,
Data_out_Q=>data_out_Q,
full=>full);
uutf5: translator
Port map( clk =>clk, --10MHz master clock
Data_out_buffer=>data_out_Q, --from buffer
done =>done,
Morse_code => Morse_code);
uutf6: morse_interpreter_top
Port map ( clk => clk, -- 10 MHz clk
morse_in =>Morse_code, -- 10 bit signal encoding morse signal
translation_done =>done, -- indicates new character is ready
end_trans=> end_trans,-- indicates that finished translating
one character
sound=>sound,
light=>light);
uutf7: square_wave_oscillator
PORT map ( clk => clk, --10 MHz clock
sound_wave =>sound_wave);-- square wave at 500Hz
88
uutf8: final_mux
port map (sound_wave =>sound_wave, --from sound oscillator
sound=>sound, --from interpreter
sound_final=>sound_final);
end Behavioral;
ii. testbench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity final_top_tb is
end final_top_tb;
architecture testbench of final_top_tb is
component final_top is
port (clk : in STD_LOGIC;
data_in : in STD_LOGIC; -- 1bit signal from AD2;
sound_final: out STD_LOGIC;
end_tick : out STD_LOGIC;
Full: out STD_LOGIC;
transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2
light: out STD_LOGIC);
end component;
signal clk, data_in,sound_final,end_tick,transmitter_data_out,light :
std_logic := '0';
constant clk_period : time := 100ns; -- 10 MHz clock
-- Data definitions
BEGIN
uuttb: final_top
port map ( clk => clk,
data_in=> data_in, -- 1bit signal from AD2;
sound_final =>sound_final,
end_tick =>end_tick,
transmitter_data_out=>transmitter_data_out,-- 1 bit signal to AD2
light=>light);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_proc: process
89
begin
data_in<='1';
wait for 10420*clk_period;
data_in<='0';
wait for 10420*clk_period;
data_in<='1';
wait for 10420*clk_period;
data_in<='0';
wait for 10420*clk_period;
data_in<='1';
wait for 10420*clk_period;
data_in<='1';
wait for 10420*clk_period;
data_in<='1';
wait for 10420*clk_period;
data_in<='0';
wait for 10420*clk_period;
data_in<='0';
wait for 10420*clk_period;
data_in<='1';
wait for 10420*clk_period;
wait for 400*clk_period;
wait;
end process;
end Testbench;
90

More Related Content

What's hot

Stick Diagram
Stick DiagramStick Diagram
Stick Diagram
Kalyan Acharjya
 
Cmos logic
Cmos logicCmos logic
Jagadeesh vlsi cv
Jagadeesh vlsi cvJagadeesh vlsi cv
Jagadeesh vlsi cv
Avinash Shetty
 
Metastability,MTBF,synchronizer & synchronizer failure
Metastability,MTBF,synchronizer & synchronizer failureMetastability,MTBF,synchronizer & synchronizer failure
Metastability,MTBF,synchronizer & synchronizer failureprashant singh
 
Timing Analysis
Timing AnalysisTiming Analysis
Timing Analysis
rchovatiya
 
Interconnects in Reconfigurable Architectures
Interconnects in Reconfigurable ArchitecturesInterconnects in Reconfigurable Architectures
Interconnects in Reconfigurable Architectures
Sudhanshu Janwadkar
 
Verilog HDL
Verilog HDL Verilog HDL
Verilog HDL
HasmukhPKoringa
 
Rc delay modelling in vlsi
Rc delay modelling in vlsiRc delay modelling in vlsi
Rc delay modelling in vlsi
Dr. Vishal Sharma
 
Verilog HDL
Verilog HDLVerilog HDL
Verilog HDL
Mantra VLSI
 
Verilog tutorial
Verilog tutorialVerilog tutorial
Verilog tutorial
Maryala Srinivas
 
Intellectual property in vlsi
Intellectual property in vlsiIntellectual property in vlsi
Intellectual property in vlsi
Saransh Choudhary
 
UNIPOLAR LOGIC FAMILY.pptx
UNIPOLAR LOGIC FAMILY.pptxUNIPOLAR LOGIC FAMILY.pptx
UNIPOLAR LOGIC FAMILY.pptx
AbubakarTv
 
Short channel effects
Short channel effectsShort channel effects
Short channel effects
ashish bait
 
CPLD xc9500
CPLD xc9500CPLD xc9500
CPLD xc9500
A B Shinde
 
Vlsi design
Vlsi designVlsi design
Vlsi design
RAMABHARATHITG
 
An Introductory course on Verilog HDL-Verilog hdl ppr
An Introductory course on Verilog HDL-Verilog hdl pprAn Introductory course on Verilog HDL-Verilog hdl ppr
An Introductory course on Verilog HDL-Verilog hdl ppr
Prabhavathi P
 
Verilog HDL Training Course
Verilog HDL Training CourseVerilog HDL Training Course
Verilog HDL Training Course
Paul Laskowski
 
Pass Transistor Logic
Pass Transistor LogicPass Transistor Logic
Pass Transistor LogicDiwaker Pant
 

What's hot (20)

Stick Diagram
Stick DiagramStick Diagram
Stick Diagram
 
Cmos logic
Cmos logicCmos logic
Cmos logic
 
Jagadeesh vlsi cv
Jagadeesh vlsi cvJagadeesh vlsi cv
Jagadeesh vlsi cv
 
Metastability,MTBF,synchronizer & synchronizer failure
Metastability,MTBF,synchronizer & synchronizer failureMetastability,MTBF,synchronizer & synchronizer failure
Metastability,MTBF,synchronizer & synchronizer failure
 
Timing Analysis
Timing AnalysisTiming Analysis
Timing Analysis
 
Interconnects in Reconfigurable Architectures
Interconnects in Reconfigurable ArchitecturesInterconnects in Reconfigurable Architectures
Interconnects in Reconfigurable Architectures
 
Verilog HDL
Verilog HDL Verilog HDL
Verilog HDL
 
Rc delay modelling in vlsi
Rc delay modelling in vlsiRc delay modelling in vlsi
Rc delay modelling in vlsi
 
Verilog HDL
Verilog HDLVerilog HDL
Verilog HDL
 
Verilog tutorial
Verilog tutorialVerilog tutorial
Verilog tutorial
 
Intellectual property in vlsi
Intellectual property in vlsiIntellectual property in vlsi
Intellectual property in vlsi
 
UNIPOLAR LOGIC FAMILY.pptx
UNIPOLAR LOGIC FAMILY.pptxUNIPOLAR LOGIC FAMILY.pptx
UNIPOLAR LOGIC FAMILY.pptx
 
Short channel effects
Short channel effectsShort channel effects
Short channel effects
 
CPLD xc9500
CPLD xc9500CPLD xc9500
CPLD xc9500
 
RV silpa Resume
RV silpa ResumeRV silpa Resume
RV silpa Resume
 
Vlsi design
Vlsi designVlsi design
Vlsi design
 
An Introductory course on Verilog HDL-Verilog hdl ppr
An Introductory course on Verilog HDL-Verilog hdl pprAn Introductory course on Verilog HDL-Verilog hdl ppr
An Introductory course on Verilog HDL-Verilog hdl ppr
 
Data Flow Modeling
Data Flow ModelingData Flow Modeling
Data Flow Modeling
 
Verilog HDL Training Course
Verilog HDL Training CourseVerilog HDL Training Course
Verilog HDL Training Course
 
Pass Transistor Logic
Pass Transistor LogicPass Transistor Logic
Pass Transistor Logic
 

Similar to Final Report - morse code.pdf

Assembler4
Assembler4Assembler4
Assembler4
Omar Sanchez
 
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
IJERA Editor
 
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic SystemVoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
Sagun Man Singh Shrestha
 
Data Encoding for Wireless Transmission
Data Encoding for Wireless TransmissionData Encoding for Wireless Transmission
Data Encoding for Wireless TransmissionSean McQuay
 
Jy3717961800
Jy3717961800Jy3717961800
Jy3717961800
IJERA Editor
 
Bm36382385
Bm36382385Bm36382385
Bm36382385
IJERA Editor
 
Training Report on embedded Systems and Robotics
Training Report on embedded  Systems and RoboticsTraining Report on embedded  Systems and Robotics
Training Report on embedded Systems and Robotics
NIT Raipur
 
8085 microprocessor
8085 microprocessor8085 microprocessor
8085 microprocessor
ganeshdabhole
 
Radio frequency identification system
Radio frequency identification systemRadio frequency identification system
Radio frequency identification systemAminu Bugaje
 
A010240110
A010240110A010240110
A010240110
IOSR Journals
 
Welcome to International Journal of Engineering Research and Development (IJERD)
Welcome to International Journal of Engineering Research and Development (IJERD)Welcome to International Journal of Engineering Research and Development (IJERD)
Welcome to International Journal of Engineering Research and Development (IJERD)
IJERD Editor
 
Serial Communication Interface with Error Detection
Serial Communication Interface with Error DetectionSerial Communication Interface with Error Detection
Serial Communication Interface with Error Detection
iosrjce
 
M010617376
M010617376M010617376
M010617376
IOSR Journals
 
IJCER (www.ijceronline.com) International Journal of computational Engineeri...
 IJCER (www.ijceronline.com) International Journal of computational Engineeri... IJCER (www.ijceronline.com) International Journal of computational Engineeri...
IJCER (www.ijceronline.com) International Journal of computational Engineeri...
ijceronline
 
how to generate sms
how to generate smshow to generate sms
how to generate smssumant reddy
 
underground cable fault location using aruino,gsm&gps
underground cable fault location using aruino,gsm&gps underground cable fault location using aruino,gsm&gps
underground cable fault location using aruino,gsm&gps
Mohd Sohail
 

Similar to Final Report - morse code.pdf (20)

Assembler4
Assembler4Assembler4
Assembler4
 
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
Analysis and Implementation of Hard-Decision Viterbi Decoding In Wireless Com...
 
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic SystemVoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
VoCoRoBo: Remote Speech Recognition and Tilt Sensing Multi-Robotic System
 
Data Encoding for Wireless Transmission
Data Encoding for Wireless TransmissionData Encoding for Wireless Transmission
Data Encoding for Wireless Transmission
 
Jy3717961800
Jy3717961800Jy3717961800
Jy3717961800
 
40120130406011 2-3
40120130406011 2-340120130406011 2-3
40120130406011 2-3
 
Bm36382385
Bm36382385Bm36382385
Bm36382385
 
CDR2(Sajjad Tarahomi)
CDR2(Sajjad Tarahomi)CDR2(Sajjad Tarahomi)
CDR2(Sajjad Tarahomi)
 
Training Report on embedded Systems and Robotics
Training Report on embedded  Systems and RoboticsTraining Report on embedded  Systems and Robotics
Training Report on embedded Systems and Robotics
 
8085 microprocessor
8085 microprocessor8085 microprocessor
8085 microprocessor
 
Radio frequency identification system
Radio frequency identification systemRadio frequency identification system
Radio frequency identification system
 
A010240110
A010240110A010240110
A010240110
 
Welcome to International Journal of Engineering Research and Development (IJERD)
Welcome to International Journal of Engineering Research and Development (IJERD)Welcome to International Journal of Engineering Research and Development (IJERD)
Welcome to International Journal of Engineering Research and Development (IJERD)
 
Serial Communication Interface with Error Detection
Serial Communication Interface with Error DetectionSerial Communication Interface with Error Detection
Serial Communication Interface with Error Detection
 
M010617376
M010617376M010617376
M010617376
 
IJCER (www.ijceronline.com) International Journal of computational Engineeri...
 IJCER (www.ijceronline.com) International Journal of computational Engineeri... IJCER (www.ijceronline.com) International Journal of computational Engineeri...
IJCER (www.ijceronline.com) International Journal of computational Engineeri...
 
how to generate sms
how to generate smshow to generate sms
how to generate sms
 
40120140504012
4012014050401240120140504012
40120140504012
 
underground cable fault location using aruino,gsm&gps
underground cable fault location using aruino,gsm&gps underground cable fault location using aruino,gsm&gps
underground cable fault location using aruino,gsm&gps
 
Lab3
Lab3Lab3
Lab3
 

Recently uploaded

Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
manasideore6
 
AP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specificAP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specific
BrazilAccount1
 
Railway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdfRailway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdf
TeeVichai
 
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdfAKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
SamSarthak3
 
ML for identifying fraud using open blockchain data.pptx
ML for identifying fraud using open blockchain data.pptxML for identifying fraud using open blockchain data.pptx
ML for identifying fraud using open blockchain data.pptx
Vijay Dialani, PhD
 
block diagram and signal flow graph representation
block diagram and signal flow graph representationblock diagram and signal flow graph representation
block diagram and signal flow graph representation
Divya Somashekar
 
space technology lecture notes on satellite
space technology lecture notes on satellitespace technology lecture notes on satellite
space technology lecture notes on satellite
ongomchris
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
Kamal Acharya
 
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdfWater Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation & Control
 
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdf
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdfGoverning Equations for Fundamental Aerodynamics_Anderson2010.pdf
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdf
WENKENLI1
 
Investor-Presentation-Q1FY2024 investor presentation document.pptx
Investor-Presentation-Q1FY2024 investor presentation document.pptxInvestor-Presentation-Q1FY2024 investor presentation document.pptx
Investor-Presentation-Q1FY2024 investor presentation document.pptx
AmarGB2
 
HYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generationHYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generation
Robbie Edward Sayers
 
ethical hacking in wireless-hacking1.ppt
ethical hacking in wireless-hacking1.pptethical hacking in wireless-hacking1.ppt
ethical hacking in wireless-hacking1.ppt
Jayaprasanna4
 
H.Seo, ICLR 2024, MLILAB, KAIST AI.pdf
H.Seo,  ICLR 2024, MLILAB,  KAIST AI.pdfH.Seo,  ICLR 2024, MLILAB,  KAIST AI.pdf
H.Seo, ICLR 2024, MLILAB, KAIST AI.pdf
MLILAB
 
J.Yang, ICLR 2024, MLILAB, KAIST AI.pdf
J.Yang,  ICLR 2024, MLILAB, KAIST AI.pdfJ.Yang,  ICLR 2024, MLILAB, KAIST AI.pdf
J.Yang, ICLR 2024, MLILAB, KAIST AI.pdf
MLILAB
 
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
Amil Baba Dawood bangali
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Dr.Costas Sachpazis
 
English lab ppt no titlespecENG PPTt.pdf
English lab ppt no titlespecENG PPTt.pdfEnglish lab ppt no titlespecENG PPTt.pdf
English lab ppt no titlespecENG PPTt.pdf
BrazilAccount1
 
road safety engineering r s e unit 3.pdf
road safety engineering  r s e unit 3.pdfroad safety engineering  r s e unit 3.pdf
road safety engineering r s e unit 3.pdf
VENKATESHvenky89705
 
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
ydteq
 

Recently uploaded (20)

Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
 
AP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specificAP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specific
 
Railway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdfRailway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdf
 
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdfAKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
AKS UNIVERSITY Satna Final Year Project By OM Hardaha.pdf
 
ML for identifying fraud using open blockchain data.pptx
ML for identifying fraud using open blockchain data.pptxML for identifying fraud using open blockchain data.pptx
ML for identifying fraud using open blockchain data.pptx
 
block diagram and signal flow graph representation
block diagram and signal flow graph representationblock diagram and signal flow graph representation
block diagram and signal flow graph representation
 
space technology lecture notes on satellite
space technology lecture notes on satellitespace technology lecture notes on satellite
space technology lecture notes on satellite
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
 
Water Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdfWater Industry Process Automation and Control Monthly - May 2024.pdf
Water Industry Process Automation and Control Monthly - May 2024.pdf
 
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdf
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdfGoverning Equations for Fundamental Aerodynamics_Anderson2010.pdf
Governing Equations for Fundamental Aerodynamics_Anderson2010.pdf
 
Investor-Presentation-Q1FY2024 investor presentation document.pptx
Investor-Presentation-Q1FY2024 investor presentation document.pptxInvestor-Presentation-Q1FY2024 investor presentation document.pptx
Investor-Presentation-Q1FY2024 investor presentation document.pptx
 
HYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generationHYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generation
 
ethical hacking in wireless-hacking1.ppt
ethical hacking in wireless-hacking1.pptethical hacking in wireless-hacking1.ppt
ethical hacking in wireless-hacking1.ppt
 
H.Seo, ICLR 2024, MLILAB, KAIST AI.pdf
H.Seo,  ICLR 2024, MLILAB,  KAIST AI.pdfH.Seo,  ICLR 2024, MLILAB,  KAIST AI.pdf
H.Seo, ICLR 2024, MLILAB, KAIST AI.pdf
 
J.Yang, ICLR 2024, MLILAB, KAIST AI.pdf
J.Yang,  ICLR 2024, MLILAB, KAIST AI.pdfJ.Yang,  ICLR 2024, MLILAB, KAIST AI.pdf
J.Yang, ICLR 2024, MLILAB, KAIST AI.pdf
 
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
NO1 Uk best vashikaran specialist in delhi vashikaran baba near me online vas...
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
 
English lab ppt no titlespecENG PPTt.pdf
English lab ppt no titlespecENG PPTt.pdfEnglish lab ppt no titlespecENG PPTt.pdf
English lab ppt no titlespecENG PPTt.pdf
 
road safety engineering r s e unit 3.pdf
road safety engineering  r s e unit 3.pdfroad safety engineering  r s e unit 3.pdf
road safety engineering r s e unit 3.pdf
 
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
一比一原版(UofT毕业证)多伦多大学毕业证成绩单如何办理
 

Final Report - morse code.pdf

  • 1. Final Project Serial to Morse Code Converter Engs 31: Digital Electronics June 2020 Students: Hana Ba-Sabaa Sayuri Tais Miyamoto Magnabosco Professor: Geoffrey Luke
  • 2. Abstract: The Morse code is a method of communication using binary signals that encode text characters as standardized sequences of two different signal durations, called ​dots and ​dashes​. The goal of this project is to create a serial to Morse code translator using VHDL code, WaveForms software, AD2 board, and a Basys-3 FPGA integrated circuit board. Our system is able to store up 100 characters of input, which can be released at any moment by the ​enter key. In order to facilitate the design and validation of the Morse code converter system, we followed top-down design and bottom-up implementation. Therefore, the functionality of the system relies on the correct implementation of 8 small functional blocks: ​SCI Receiver​, ​SCI Transmitter​, ​Check Characte​r, ​Buffer​,​Morse Translator​, ​Morse interpreter​, ​Square Wave Oscillator​, and Final MUX. The SCI blocks receive the binary data coming from the AD2 block and concatenate them in ASCII formatting. The characters are then sent back to the AD2 so the user can see on the screen their input. The SCIs work at a baud rate of 9,600 bits/sec. The Check Character block verifies if the ​enter key has been pressed to trigger the translation of the bits in the system. The Buffer stores the characters inputted by the user, while the translator transforms each bit into its Morse code equivalent – a representation of dots (01) and dashes (11). The Interpreter uses such formatting as a time indicator for the sound and light signals. The ​Square Wave Oscillator and Final MUX blocks take care of the audio aspect of the system. They generate square waveforms with ideal frequencies to form pitches recognizable to human ears (500Hz). The result of each component block is satisfying and in alignment with the specifications for the whole system. Our design went through synthesis, implementation and bitstream generation successfully. We also programmed our board accordingly. However, during the demonstration, our board did not behave as expected. We believe that the problem may have been with our wiring. 1
  • 3. Table of Contents: Introduction 3 Approach 4 System Design 4 Signal Generation and the AD2 Board 5 SCI Receiver 5 SCI Transmitter 7 Check Character 10 Buffer 10 Morse Translator 10 Morse interpreter 11 Square Wave Oscillator 13 Final MUX 13 Memory Map 13 Testing 13 Conclusions 33 Acknowledgements 33 Appendix (VHDL Code): 33 SCI Receiver 33 SCI Transmitter 45 Check Character 56 Buffer 58 Morse Translator 62 Morse Interpreter 67 Square Wave Oscillator 82 Final MUX 83 Final Top Code (Shell File) 84 2
  • 4. Introduction The device designed for this project is a Serial to Morse Code Converter. Using the Serial Communications Interface (SCI), the user inputs characters into the system and the device outputs the Morse code signal for it. The circuitry designed receives the character data and converts it into an encoded format using binary signals. This step allows the read out of the character in terms of dots and dashes, regulated by a precise timing. In this design, the fundamental unit of time, 𝑇, is 0.1 s long. The inputs of the circuitry are a 10MHz master clock and a 1 bit-signal coming from the AD2 board. Each bit received from the AD2 board is stored in a shift register at a baud rate of 9,600 bits/sec. The outputs of the system are a light and sound signal, a “full” signal that lights up a LED when the user inputted 100 chracter, as well as a 1-bit signal that serially transmits back to the AD2 the character originally inputted by the user. We also have an end_tick to indicate when all the bits of the character were sent back to the AD2. This is represented by the schematics below: The system has a buffer that stores up to 100 characters. To have the message decoded in sound and light format, the user must press enter and wait until all the characters have been outputted to start writing again. If the user inputs 100 characters, the buffer gets full and a LED lights up on the board to indicate that. In case the user keeps writing, the characters will not be saved in the buffer and will be lost. To release the message stored, the user must press the enter key. If the enter key is never pressed, then the “full” light will be off. Our system converts both lower and upper case letters, and numbers 0-9. Any other character will be recognized and outputted as zero. 3
  • 5. Approach In order to facilitate the design and validation of the morse code converter system, we follow top-down design and bottom-up implementation. We broke down the system into the following small components and built and tested each one of them individually: 1. Signal Generation and the AD2 Board 2. SCI Receiver 3. SCI Transmitter 4. Check Characte​r 5. Buffer 6. Morse Translator 7. Morse interpreter 8. Square Wave Oscillator 9. Final MUX For the components that needed a controller and a datapath, each part was designed and tested separately using the EDAPlayground platform. Each component was then individually wired and tested in Vivado for validation. After confirming that each part was matching the design specifications, we built a shell and wired all the signals together in order to have a working system. Our team communicated daily and split the work accordingly. Components 2, 3, 7, and 8 were the main responsibility of Sayuri, while components 1, 4, 5, 6, and 9 were the main responsibility of Hana. We would frequently meet and chat to discuss which signals were needed in each component so our overall system would connect. Additionally, we helped each other in code debugging and coordinated to attend TA hours together. System Design The following block diagram represents the overall architecture of the system: 4
  • 6. 1. Signal Generation and the AD2 Board In order to decide what letters the Morse code generator will make, the user sends characters to the Basys3 board using the Serial Communications Interface (SCI). The SCI signal is generated using the WaveForms software and the AD2 board, and sent to one digital I/O pin on the Basys3. Each character entered is converted into the form of an 8-bit ASCII character. Subsequently, the AD2 board outputs each bit of the character, one at a time. This part does not require any VHDL design. 2. SCI Receiver The SCI Receiver is a 10-bit shift register that takes in one bit at a time from the AD2 board, at the baud rate of 9,600 bits/sec, concatenates them into a single vector, removes the start bit and stop bits, and shifts the 8-bit character result. The process is controlled by a state machine. The receiver’s inputs are the serial data stream from the AD2 and a 10 MHz master clock. Its outputs are the 8-bit data, in parallel, and a done_tick signal that goes high when the output is ready. This is summarized by the following diagram: 5
  • 7. a. Double Flop Synchronizer Designed accordingly to the following schematics to provide an additional clock period and resolve the metastability in the process. b. Datapath The serial data coming from the AD2 board is right-shifted into a 10-bit shift register, called shift_reg, ​which is clocked by the 10 MHz clock, and enabled by a signal ​shift_en from the controller. It has a ​shift_clr input for resetting. The bits 8 down to 1 of the shift register may be parallel-loaded out when enabled by the control signal ​output_en. c. Controller The controller consists of a 6-state finite state machine and three counters, as summarized in the diagram at the end of this section. The “waiting” states were programmed to follow the baud rate of 9,600 bits/sec. In these states, the machine counts clock edges to locate the center of each data bit. For the first bit, it counts ​N​/2 clock edges, while for the remaining bits, it counts up to N clock edges. Additionally, the machine relies on the counter that keeps track of how many bits have been transmitted and stored in the shift register. When there is the start bit + 9 other bits inside the register (count_shift=8), ​output_en goes high so the datapath outputs the 8-bit ASCII character. Each time the controller receives the start bit from the AD2 (​data_in_sync = 0​), it leaves its idle state and goes to its ​wait_start_bit state. In this state, ​shift_en goes high and the start bit is stored in the shift register. The machine stays in ​wait_start_bit state for half T (520 clock cycles, based on the 10 MHz clk period) until ​count_half_T signal goes high; the machine then moves to the ​shift_reg state. In ​shift_reg, the ​shift_en goes high and allows the bit coming from the AD2 to be stored in the shift register. The machine then enters the wait_other_bits state, where it waits for T (1042 clk cycles, based on the 10 MHz clk), then ​count_T goes high and the machine returns to the ​shift_reg ​state to receive a new bit. After 10 bits of data have been put into the shift register, the machine moves to ​shift_output state, where ​output_en ​goes high and the 8-bit ASCII code is parallely shifted out of the register. Additionally, the output ​done_tick ​goes high to signal that 6
  • 8. the ASCII data is available. Then, it goes to the ​clear state and returns to ​idle to wait for the next start bit. 3. SCI Transmitter The SCI Transmitter gets the 8-bit character signal from the SCI Transmitter and sends it back to the AD2, in order to confirm to the user that the system is correctly storing 7
  • 9. the character they input. Therefore, the transmitter works in reverse to the receiver; its inputs are the 8-bit data, in parallel, and the done_tick signal from the SCI Receiver, indicating that a new character is ready. Its outputs are ten 1-bit serial data at the same baud rate of 9,600 bits/sec, and an end_tick that goes high when the last bit of the character is sent to the AD2. The transmitter consists of a 10-bit shift register that takes the 8-bit signal from the receiver, concatenates it with a start and end bits (start = 0; end =1), and outputs one bit at a time by left shifting the bits out of the register. This is summarized by the following diagram: a. Double Flop Synchronizer Designed to provide an additional clock period and resolve the metastability in the process, following the schematics of the SCI Receiver flop synchronizer. b. Datapath The parallel data coming from the SCI Receiver is concatenated with a start and end bit into a 10-bit register​, ​which is clocked by the 10 MHz clock, and enabled by a signal ​load_en from the controller. It has a ​reg_clr input for resetting. The bits inside the shift register may be loaded out serially by right-shifting when enabled by the control signal ​output_en. c. Controller The controller consists of a 5-state finite state machine and two counters, as explained in the diagram below: 8
  • 10. The ​wait_T state was programmed to follow the baud rate of 9,600 bits/sec. In this state, the machine counts up to N clock edges before output-shifting each bit. Another counter that regulates the state machine is the ​count_shift​, which keeps track of how many bits have been output back to the AD2. Each time the controller receives the high signal of ​done_tick from the SCI Receiver, it leaves its idle state and goes to its ​shift_load state. Here, ​load_en signal goes high which allows the datapath to get the 8-bit data coming from the SCI Receiver and concatenate it with a start and end bits into a 10-bit register. The machine then moves to ​shift_nums state, where ​output_en goes high and triggers the right-shifting out of a single bit. Subsequently, it goes to wait_T state, where it waits 9
  • 11. for T (1042 clk cycles, based on the 10 MHz clk), then ​count_T goes high and the machine returns to the ​shift_nums ​state to output another bit. After 10 bits of data have been outputted (c​ount_shift​=9), the machine goes to the ​clear state, where reg_clr ​and ​end_tick ​go high to signal that all the bits of that character have been transmitted. Then, the controller returns to ​idle​ to wait for another character. 4. Check Character This block checks whether the character coming from the SCI Receiver is an enter key or not. If it is, the check_character block will output a signal, ​read_en​, with a logic high, which will later enable the buffer to read all the characters that have been previously stored in the queue. 5. Buffer The buffer is a 101 characters long 8-bit queue that stores the characters inputted by the user until they press the enter key. When the user inputs 100 characters successfully , that is they terminate their input with an enter key, a signal called ‘full’ (having a logic high) is outputted by this buffer. This signal turns on an LED light on the board, which indicates to the user that their input has been successfully saved in the queue. The buffer is designed so that it only stores data in the queue both if a new character is inputted by the user and there is space left in the queue. Therefore, if the user inputs 100 characters and forgets to press the enter key, their characters will not be stored in the queue and, accordingly, their Morse code equivalent will never be outputted. To test our code, we modified the queue so that it is 6 characters long. 6. Morse Translator This block takes the data_out 8-bit signal coming from the buffer and translates the ASCII that the signal represents to its Morse code equivalent. Using the table provided to us in the project handout, we hard coded the Morse combination of dots and dashes for each character (letters and numbers). We represented dots with 01 and dashes with 11. Because the Morse code characters have different lengths (the letter E is only a dot, while the number zero is 5 dashes), our Morse code is 10-bits long, to accommodate the longest characters. Accordingly, if a character has less dots and dashes, 00 can be used 10
  • 12. to pad it and ensure it is the same length as the other longer characters. We also accounted for lowercase letters, which will translate to their uppercase Morse code equivalents. In case a random character is inputted by the user, this block will output the Morse code of a zero, i.e., 11 11 11 11 11. 7. Morse interpreter This component receives the data coming from the translator and interprets the 01, 11, and 00 bits of the data as a time indicator for the sound and light signals. The speed of the Morse code is determined by a time T=0.1s. A dot is on for 𝑇 and dash is on for 3𝑇. In between dots and dashes within a single letter there is a gap of 𝑇. In between letters there is a gap of 3𝑇. In between words there is a gap of 7𝑇. Its inputs are the 10-bit data from the translator, and ​translation_done ​tick that indicates a new character was translated. It outputs signals for sound and light, and an end_trans tick that goes high whenever the character is done being interpreted. This component consists of a register and a controller. The register consists of a 10-bit shift register that takes the 10-bit signal from the translator, reads and shifts the two left-most bits, and outputs them as dots (01), dashes (11), or end of character (00). Intermediate signals trigger the state machine and the datapath as demonstrated in the diagram below: a. Datapath The parallel data coming from the Translator is put into the register, which is clocked by the 10 MHz clock, and enabled by a signal ​load_en from the controller. If the character is a space (all zeros), then the register sends the signal ​space to the controller; otherwise, it sends the signal ​no_space​. Triggered by the signal check_bits_en from the controller, the datapath analyzes the bits 9 down to 8 of the register; if they are 01, it outputs the signal ​dot as high; if they are 11, it outputs ​dash as high; if they are 00; it outputs ​end_char as high. The signal ​shift_en triggers the left-shift of the two left-most bits of the register, so the next two bits can be decoded. The signals ​count_T_en​, c​ount_3T_en​, and ​count_7T_en, ​dictate when ​light and 11
  • 13. sound signals will be high or low and for how long, following the speed of the Morse code of T=0.1s. b. Controller The controller consists of a 10-state finite state machine and several counters to mark the time for dots and dashes for each character, as explained in the diagram below: The “timing” states were programmed to follow the speed of the morse code as T=0.1s. In these states, the machine counts clock edges up to T, 3T, or 7T. Each time the translator has a new character available, (​translation_done = 1​), it leaves its idle state and goes to its ​shift_register ​state. In this state, ​load_en goes high so the data from the translator is stored in the register in the datapath. If the character we receive is a space, ​space=1 and we move to ​time_7T state. The machine stays in this state for 0.7s until count_7T_TC goes high and the machine moves to the clear​ state. However, if the data received is not a space character, ​not_space=1​, and the machine moves to ​check_bits ​state. Here, ​check_bits_en goes high and we receive back from the datapath the information of whether we have a ​dot​, a ​dash, ​or the end_char​. 12
  • 14. A. If ​dash=1​, we move to t​ime_3T state. We stay in this state for 0.3s, held by a counter. When ​count_3T_TC = 1, we move to time_within_letters​ state. B. If ​dot=1​, we move to ​time_T state. We stay in this state for 0.1s, held by a counter. When ​count_T_TC = 1, we move to ​time_within_letters state. C. If ​end_char=1​, we move to ​time_between_letters state. We stay here for 0.3s. Then ​count_between_letters_TC goes high and we move to the ​clear ​state. In the time_within_letters state, the signal ​count_within_char_en=1, ​which triggers the count of clk cycles up to 0.3s. Then, the terminal count goes high and we move to the ​shift_bits state. Here, the signal ​shift_en goes high and allows for the bis in the shift register in the datapath to shift left and expose the next encoded morse signal. Then, the machine goes back to ​check_bits state to verify the presence of dot, dash, or end of character bits. Once in the ​clear state, ​end_trans goes high to indicate we are done outputting the morse for that character. Then it returns to ​idle​ to wait for the next character. 8. Square Wave Oscillator This component creates a square wave to output the sound at a frequency of 500Hz, which is an audible range for human beings. Its input is the master clock at 10MHz and its output is the ​sound_wave​. The ​sound_wave ​stays high for 2000 clk cycles. 9. Final MUX This component “AND” the ​sound_wave signal from the Square Wave Oscillator and the ​sound signal coming out of the Morse interpreter, so we only have audible sound while the ​sound ​signal is high. Memory Map In this design, we used 4 10-bit registers for the SCI receiver and transmitter. For the queue, we had to have enough memory to store 8bits *100. For the translator, we used enough memory to encode a 10-bit representation for each character. The following graphs summarize the post-implementation memory data for our circuitry: 13
  • 15. Testing 1. Components When testing each component, we addressed each error and warning message received, to make sure they would not be a major issue when assembling the whole system. a. Signal Generation and the AD2 Board We connected the receiver and transmitter of the AD2 Board. Below is a screenshot of our waveform for ‘hello world’. b. SCI Receiver 14
  • 16. i. Double Flop Synchronizer ii. Datapath 15
  • 18. 17
  • 19. 18
  • 20. c. SCI Transmitter i. Double Flop Synchronizer ii. Datapath 19
  • 23. 22
  • 24. f. Morse Translator g. Morse interpreter i. Datapath: 23
  • 26. 25
  • 27. 26
  • 28. 27
  • 30. h. Square Wave Oscillator 29
  • 31. i. Full Design Schematics: 1- ​SCI Receiver 30
  • 32. 2- SCI Transmitter 3- Check Character 3​-Queue 31
  • 35. 2. Overall System a. Final Schematic of All the Parts Together: 34
  • 36. Conclusions Each component of our project successfully meets the requirements specified in the introduction. When wired together, all the blocks were successfully implemented into the Basys3 board as well. However, the board did not behave as expected. Both the LEDs for the Morse code light and for the “full” buffer signal were always on, and no sound was coming out of the WaveForm software. Because we did not get any error messages through our implementation and each separate component was behaving as expected, we believe that the issue was with wiring the board with the AD2 component. If we were to design this project again, we would modify the code for the buffer, so the “full” signal for the LED lights up when the user has input 100 chracters and stays on until the input is the enter ​key. Another modification would be to combine the block “Square Wave Oscillator” and “Final MUX”, since they both deal with the sound output of the Morse code. Additionally, we would also include a clock divider on our top shell to slow down the Basys board clock. We would keep our top-down design and bottom-up implementation, as we believe it is a good approach to debugging and testing. Acknowledgements Throughout the project, we referred back to the projects we built in the lab sections for guidance on how to break down our system in small components and follow top-down design and bottom-up implementation. We referred to the slides provided by Professor Luke to set up the parameters for the WaveForms software and for connecting the Basys3 and the AD2 component. These slides also guided us to connect the Morse code ​sound_out to the oscilloscope to play the sound. The buffer was built upon the code we wrote for this year’s “Exercise 19: Queues”. The SCI Receiver and SCI transmitter were designed by adapting the instructions of Lab5 of Spring 2016. The XDC file provided in this year’s Lab 4 was used as a template to generate our own constraints. We would like to acknowledge the help of TAs Ruthie, Matthew, and Shailin, for their guidance and support throughout the project. We are also grateful for our classmates Akwasi and Tyler, who kept us company throughout this project and made sure we always had fun music playing in Mclaughlin’s common room. Appendix (VHDL Code): 1. SCI Receiver a. Double-Flop Synchronizer i. Code -- Code your design here library IEEE; use IEEE.std_logic_1164.all; 35
  • 37. ENTITY SCI_receiver_double_flop IS PORT ( clk : in STD_LOGIC; --10MHz clock data_in : in STD_LOGIC; -- 1bit signal from AD2 data_sync : out STD_LOGIC); -- 1bit signal after being delayed by 2 clk cycles end SCI_receiver_double_flop; architecture behavior of SCI_receiver_double_flop is --Signals signal d_in_sync, dsync : std_logic :='0'; -- signals for double flop synchronizer BEGIN -- Double-flop synchronizer double_flop_sync: process (clk) begin if rising_edge(clk) then dsync <= data_in; -- flop 1 data_sync <= dsync; -- flop 2 end if; end process; end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; entity SCI_receiver_double_flop_tb is end SCI_receiver_double_flop_tb; architecture testbench of SCI_receiver_double_flop_tb is component SCI_receiver_double_flop PORT ( clk : in STD_LOGIC; --10MHz clock data_in : in STD_LOGIC; -- 1bit signal from AD2 data_sync : out STD_LOGIC); -- 1bit signal after being delayed by 2 clk cycles end component; -- signals signal clk, data_in, data_sync: std_logic := '0'; constant clk_period: time := 100ns; -- 10MHz clock begin uut : SCI_receiver_double_flop PORT MAP( 36
  • 38. clk => clk, data_in=> data_in, data_sync=> data_sync); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 1*clk_period; data_in<='1'; wait for 1*clk_period; data_in<='0'; wait for 1*clk_period; data_in<='1'; wait for 1*clk_period; data_in<='0'; wait for 1*clk_period; data_in<='1'; wait for 1*clk_period; data_in<='0'; wait for 1*clk_period; data_in<='1'; wait for 1*clk_period; data_in<='0'; wait for 1*clk_period; end process; end testbench; b. Controller i. code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY SCI_receiver_controller IS PORT ( clk : in STD_LOGIC; --10MHz clock data_sync: in STD_LOGIC; -- 1bit signal from double flop synchronizer shift_en : out STD_LOGIC; -- send to datapath shift_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath done_tick : out STD_LOGIC); -- indicates new data is ready end SCI_receiver_controller; 37
  • 39. architecture behavior of SCI_receiver_controller is --signals type state_type is (idle, wait_start_bit, wait_other_bits, shift_reg, shift_output, clear); -- states of FSM signal current_state, next_state : state_type := idle; signal count_halfT, count_T, count_halfT_en, count_T_en,output_en_signal, shift_en_signal: std_logic:= '0'; signal count_shift,count_clk_cycles, count_Tclk_cycles: integer:=0; BEGIN -- update state machine states stateUpdate: process(clk) BEGIN if rising_edge(clk) then current_state <= next_state; end if; end process stateUpdate; -- controller controller: process (current_state,count_halfT, count_T, data_sync, count_shift) begin output_en_signal <= '0'; shift_en_signal <='0'; case (current_state) is when idle=> shift_clr<='0'; shift_en<='0'; output_en<='0'; done_tick<='0'; count_halfT_en<='0'; count_T_en <='0'; if data_sync='0' then -- receives start bit next_state<=wait_start_bit; end if; when wait_start_bit=> shift_clr<='0'; shift_en<='0'; output_en<='0'; done_tick<='0'; count_halfT_en<='1'; count_T_en <='0'; if count_halfT='1' then -- after waited T/2 next_state<=shift_reg; end if; 38
  • 40. when wait_other_bits=> shift_clr<='0'; shift_en<='0'; output_en<='0'; done_tick<='0'; count_halfT_en<='1'; count_T_en <='1'; if count_T='1' then -- after waited T next_state<=shift_reg; end if; when shift_reg=> shift_clr<='0'; shift_en<='1'; shift_en_signal<='1'; output_en<='0'; done_tick<='0'; count_halfT_en<='1'; count_T_en <='1'; if count_shift = 8 then -- if already input 9 bits next_state<=shift_output; else next_state<=wait_other_bits; end if; when shift_output=> shift_clr<='0'; shift_en<='0'; output_en<='1'; output_en_signal<='1'; done_tick<='1'; count_halfT_en<='0'; count_T_en <='0'; next_state<=clear; when clear=> shift_clr<='1'; -- clear shift register shift_en<='0'; output_en<='0'; done_tick<='0'; count_halfT_en<='0'; count_T_en <='0'; next_state<=idle; end case; end process; -- time we need to wait after receiving 1 bit so it matches a baud rate of 9600 half_time: process (clk, count_halfT_en) begin 39
  • 41. if rising_edge (clk) then if count_halfT_en='1' then count_clk_cycles <= count_clk_cycles+1; if count_clk_cycles = 520 then -- num of clk cycles to count for T/2, based on a 10Mhz clk period count_halfT <= '1'; -- flags that T/2 has passed; T/2 = (1/2) * (1/9600) else count_halfT<='0'; end if; if count_clk_cycles = 1041 then -- num of clk cycles (1042 clck cycles) to count for T, based on a 10Mhz clk period count_clk_cycles <=0; -- resets counter after reaching 1042 clock cycles end if; end if; end if; end process; -- time we need to wait after receiving other bits so it matches a baud rate of 9600 full_time: process (clk, count_T_en) begin if rising_edge (clk) then if count_T_en='1' then count_Tclk_cycles <= count_Tclk_cycles+1; if count_Tclk_cycles = 1041 then -- num of clk cycles (1042 clck cycles) to count for T, based on a 10Mhz clk period count_T<='1'; -- flags that T has passed; T = 1/9600 count_Tclk_cycles <=0; -- resets counter after reaching 208 clock cycles else count_T<='0'; end if; end if; end if; end process; -- counting the numb of bits in the shift register bit_count: process (clk, shift_en_signal, output_en_signal) begin if rising_edge(clk) then if shift_en_signal='1' then -- in shift state count_shift<=count_shift+1; end if; if output_en_signal ='1' then -- indicates we have 9 bits of data count_shift<=0; end if; end if; 40
  • 42. end process; end behavior; -- Math for T and T/2: --T<= 1/9600; -- T for the baud rate in seconds --num_clk_cycles <= T/(100*10^-9); -- for 2MHz clock -- 1042 num_clk cycles (rounded up) ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity SCI_receiver_controller_tb is end SCI_receiver_controller_tb; architecture testbench of SCI_receiver_controller_tb is component SCI_receiver_controller PORT ( clk : in STD_LOGIC; --10MHz clock data_sync: in STD_LOGIC; -- 1bit signal from double flop synchronizer shift_en : out STD_LOGIC; -- send to datapath shift_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath done_tick : out STD_LOGIC); end component; -- signals signal clk, shift_en, shift_clr, output_en, done_tick: std_logic := '0'; signal data_sync: std_logic:= '1'; constant clk_period: time := 100ns; -- 10MHz clock begin uut : SCI_receiver_controller PORT MAP( clk => clk, data_sync=> data_sync, shift_en=> shift_en, shift_clr=>shift_clr, output_en=>output_en, done_tick=>done_tick); 41
  • 43. clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 5*clk_period; data_sync<='0'; -- receives start bit wait for 1042*clk_period; data_sync<='1'; wait for 1042*clk_period; data_sync<='0'; wait for 1042*clk_period; data_sync<='1'; wait for 1042*clk_period; data_sync<='0'; wait for 1042*clk_period; data_sync<='1'; wait for 1042*clk_period; data_sync<='0'; wait for 1042*clk_period; data_sync<='1'; wait for 1042*clk_period; data_sync<='0'; wait for 1042*clk_period; data_sync<='1'; wait for 1042*clk_period; wait for 400*clk_period; end process; end testbench; c. Datapath i. code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY SCI_receiver_datapath IS PORT ( clk : in STD_LOGIC; --10MHz clock data_sync : in STD_LOGIC; -- 1bit signal from flop synchronizer 42
  • 44. shift_en : in STD_LOGIC; -- receiveing from controller shift_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of parallel data end SCI_receiver_datapath; architecture behavior of SCI_receiver_datapath is --Signals signal shift_reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10 bits BEGIN -- Shift and output registers registers: process (clk, output_en, shift_en, shift_clr) begin if rising_edge(clk) then if shift_clr ='1' then -- clears what is inside the shift register shift_reg<="0000000000"; elsif shift_clr ='0' then -- if doesn't want to clear the register if shift_en='1' then -- shift right; most significant bit of the register gets what is on d_in_sync (the bit coming from AD2 and delayed by the double-flop) shift_reg <= data_sync & shift_reg(9 downto 1); end if; if output_en ='1' then -- when load register is enabled data_out <= shift_reg(8 downto 1); -- does not copy start and end bit end if; end if; end if; end process; end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity SCI_receiver_datapath_tb is end SCI_receiver_datapath_tb; architecture testbench of SCI_receiver_datapath_tb is 43
  • 45. component SCI_receiver_datapath PORT ( clk : in STD_LOGIC; --10MHz clock data_sync : in STD_LOGIC; -- 1bit signal from flop synchronizer shift_en : in STD_LOGIC; -- receiveing from controller shift_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller data_out : out STD_LOGIC_VECTOR(7 downto 0)); end component; -- signals signal clk, data_sync, shift_en, shift_clr, output_en: std_logic := '0'; signal data_out: std_logic_vector(7 downto 0) := (others=>'0'); constant clk_period: time := 100ns; --10MHz clock begin uut : SCI_receiver_datapath PORT MAP( clk => clk, data_sync=> data_sync, shift_en=> shift_en, shift_clr=>shift_clr, output_en=>output_en, data_out=>data_out); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin shift_en<='1'; -- allows shift register to receive the data wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; data_sync<='0'; wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; data_sync<='0'; wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; data_sync<='0'; wait for 1*clk_period; 44
  • 46. data_sync<='1'; wait for 1*clk_period; data_sync<='0'; wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; -- shift register must be 101010101 in the end shift_en<='0'; wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; data_sync<='1'; wait for 1*clk_period; -- tries adding 11, but shift enable signal is not on, so shift register must keep its value output_en<='1'; -- output what is on the shift register wait for 1*clk_period; shift_clr<='1'; -- clears the shift register wait for 1*clk_period; wait; end process; end testbench; d. Shell i. code library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity SCI_Receiver_top is Port ( clk : in STD_LOGIC; data_in : in STD_LOGIC; -- 1bit signal from AD2; done_tick: out STD_LOGIC; data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of parallel data end SCI_Receiver_top; architecture Behavioral of SCI_Receiver_top is component SCI_receiver_controller IS PORT ( clk : in STD_LOGIC; --10MHz clock data_sync: in STD_LOGIC; -- 1bit signal from double flop synchronizer shift_en : out STD_LOGIC; -- send to datapath shift_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath done_tick : out STD_LOGIC); -- indicates new data is ready end component; 45
  • 47. component SCI_receiver_datapath IS PORT ( clk : in STD_LOGIC; --10MHz clock data_sync : in STD_LOGIC; -- 1bit signal from flop synchronizer shift_en : in STD_LOGIC; -- receiveing from controller shift_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of parallel data end component; component SCI_receiver_double_flop IS PORT ( clk : in STD_LOGIC; --10MHz clock data_in : in STD_LOGIC; -- 1bit signal from AD2 data_sync : out STD_LOGIC); -- 1bit signal after being delayed by 2 clk cycles end component; signal shift_en,shift_clr,output_en: STD_LOGIC :='0'; signal data_sync: STD_LOGIC :='1'; begin uut : SCI_receiver_controller port map ( clk => clk, --10MHz clock data_sync => data_sync, -- 1bit signal from double flop synchronizer shift_en => shift_en, -- send to datapath shift_clr => shift_clr, -- send to datapath output_en => output_en, -- send to datapath done_tick => done_tick); -- indicates new data is ready uut2: SCI_receiver_datapath port map ( clk => clk, --10MHz clock data_sync => data_sync, -- 1bit signal from flop synchronizer shift_en => shift_en, -- receiveing from controller shift_clr => shift_clr, -- receiveing from controller output_en => output_en, -- receiveing from controller data_out => data_out);-- 8 bits of parallel data uut3: SCI_receiver_double_flop port map ( clk => clk, --10MHz clock data_in => data_in, -- 1bit signal from AD2 data_sync => data_sync); -- 1bit signal after being delayed by 2 clk cycles end Behavioral; 46
  • 48. 2. SCI Transmitter a. Double-Flop Synchronizer i. code -- Code your design here library IEEE; use IEEE.std_logic_1164.all; library IEEE; use IEEE.std_logic_1164.all; ENTITY SCI_transmitter_double_flop IS PORT ( clk : in STD_LOGIC; --10MHz clock receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit signal from SCI receiver receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit signal after being delayed by 2 clk cycles end SCI_transmitter_double_flop; architecture behavior of SCI_transmitter_double_flop is --Signals signal dsync : std_logic_vector(7 downto 0) :="00000000"; -- signals for double flop synchronizer BEGIN -- Double-flop synchronizer double_flop_sync: process (clk) begin if rising_edge(clk) then dsync <= receiver_data; -- flop 1 receiver_data_sync <= dsync; -- flop 2 end if; end process; end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; entity SCI_transmitter_double_flop_tb is end SCI_transmitter_double_flop_tb; architecture testbench of SCI_transmitter_double_flop_tb is component SCI_transmitter_double_flop 47
  • 49. PORT ( clk : in STD_LOGIC; --10MHz clock receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit signal from SCI receiver receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit signal after being delayed by 2 clk cycles end component; -- signals signal receiver_data, receiver_data_sync: std_logic_vector(7 downto 0) := "00000000"; signal clk : std_logic :='0'; constant clk_period: time := 100ns; --10MHz clock begin uut : SCI_transmitter_double_flop PORT MAP( clk=> clk, receiver_data=> receiver_data, receiver_data_sync=> receiver_data_sync); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 1*clk_period; receiver_data<="11111111"; wait for 1*clk_period; receiver_data<="10101010"; wait for 1*clk_period; end process; end testbench; b. Controller i. code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY SCI_transmitter_controller IS PORT ( clk : in STD_LOGIC; --10 MHz clock 48
  • 50. data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from flop synchronizer done_tick : in STD_LOGIC; -- from controller of receiver; indicates that new 8bit data is ready load_en : out STD_LOGIC; -- send to datapath reg_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end SCI_transmitter_controller; architecture behavior of SCI_transmitter_controller is --Signals type state_type is (idle, wait_T, shift_load, shift_nums, clear); -- states of FSM signal current_state, next_state : state_type := idle; signal count_halfT, count_T, count_T_en,end_tick_signal, output_en_signal: std_logic:= '0'; signal count_shift, count_Tclk_cycles: integer:=0; BEGIN -- update state machine states stateUpdate: process(clk) BEGIN if rising_edge(clk) then current_state <= next_state; end if; end process stateUpdate; -- controller controller: process (current_state, done_tick, count_shift, count_T) begin -- defaults; will only change inside the states load_en<='0'; reg_clr<='0'; output_en<='0'; end_tick<='0'; count_T_en <='0'; output_en_signal<='0'; case (current_state) is when idle=> if done_tick='1' then -- ready to receive new bits next_state<=shift_load; end if; 49
  • 51. when shift_load=> load_en<='1'; -- data goes to shift register next_state<=shift_nums; when shift_nums=> output_en<='1';-- allows numbers to get shifted out output_en_signal<='1'; if count_shift = 9 then -- after shifting 10 bits of data next_state<= clear; else next_state<= wait_T; end if; when wait_T=> count_T_en <='1'; if count_T='1' then -- after waited T next_state<=shift_nums; end if; when clear=> end_tick<='1'; -- indicates that finished shifitng data out end_tick_signal<='1'; reg_clr<='1'; -- clear register next_state<=idle; end case; end process; -- count how many bits have been output bit_count: process (clk, output_en_signal, end_tick_signal) begin if rising_edge(clk) then if output_en_signal='1' then -- in shift state count_shift<=count_shift+1; end if; if end_tick_signal ='1' then -- indicates we have 10 bits of data count_shift<=0; end if; end if; end process; -- counter for baud rate time_T: process (clk, count_T_en) begin if rising_edge (clk) then if count_T_en='1' then count_Tclk_cycles <= count_Tclk_cycles+1; if count_Tclk_cycles = 1041 then -- num of clk cycles (1042 clck cycles) to count for T, based on a 10Mhz clk period count_T<='1'; -- flags that T has passed; T = 1/9600 50
  • 52. count_Tclk_cycles <=0; -- resets counter after reaching 1042 clock cycles else count_T<='0'; end if; end if; end if; end process; end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity SCI_transmitter_controller_tb is end SCI_transmitter_controller_tb; architecture testbench of SCI_transmitter_controller_tb is component SCI_transmitter_controller PORT ( clk : in STD_LOGIC; --10 MHz clock data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from flop synchronizer done_tick : in STD_LOGIC; -- from controller of receiver; indicates that new 8bit data is ready load_en : out STD_LOGIC; -- send to datapath reg_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end component; -- signals signal clk, done_tick, load_en, reg_clr, output_en, end_tick: std_logic := '0'; signal data_in_sync: std_logic_vector(7 downto 0):= "00000000"; constant clk_period: time := 100ns; --10 MHz clock begin uut : SCI_transmitter_controller PORT MAP( 51
  • 53. clk => clk, data_in_sync=> data_in_sync, done_tick=> done_tick, load_en=> load_en, reg_clr=>reg_clr, output_en=>output_en, end_tick=>end_tick); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 5*clk_period; done_tick<='1'; -- receives new data wait for 1*clk_period; done_tick<='0'; wait for 1*clk_period; data_in_sync<="10101010"; wait for 10420*clk_period; wait for 400*clk_period; end process; end testbench; c. Datapath i. Code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY SCI_transmitter_datapath IS PORT ( clk : in STD_LOGIC; --10 MHz clock data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from flop synchronizer load_en : in STD_LOGIC; -- receiveing from controller reg_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller transmitter_data_out : out STD_LOGIC);-- 1 bit signal to AD2 52
  • 54. end SCI_transmitter_datapath; architecture behavior of SCI_transmitter_datapath is --Signals signal shift_reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10 bits of data signal fill_reg: std_logic:= '0'; -- used to left shift bits out of the register signal start_bit: std_logic:='0'; -- start bit to be added to the signal for each letter signal end_bit: std_logic:='1'; -- end bit to be added to the signal for each letter BEGIN -- Shift and output registers registers: process (clk, output_en, load_en, reg_clr) begin if rising_edge(clk) then if reg_clr ='1' then -- clears what is inside the shift register shift_reg<="0000000000"; elsif reg_clr ='0' then -- if doesn't want to clear the register if load_en='1' then -- shift register gets the value of the data coming in (the 8-bits coming from SCI transmitter and delayed by the double-flop) shift_reg <= (start_bit)&(data_in_sync)&(end_bit); -- adds start and end bit and save value in a shift register else shift_reg<= shift_reg; -- shift reg hold its current value end if; if output_en ='1' then -- when load register is enabled transmitter_data_out <= shift_reg(9); -- outputs first bit of data shift_reg<= shift_reg(8 downto 0)&fill_reg; -- left shifting the bits out of the register end if; end if; end if; end process; end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; 53
  • 55. use IEEE.numeric_std.all; entity SCI_transmitter_datapath_tb is end SCI_transmitter_datapath_tb; architecture testbench of SCI_transmitter_datapath_tb is component SCI_transmitter_datapath PORT ( clk : in STD_LOGIC; --10 MHz clock data_in_sync: in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from SCI receiver load_en : in STD_LOGIC; -- receiveing from controller reg_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller data_out : out STD_LOGIC);-- 1 bit signal to AD2 end component; -- signals signal clk, data_out, load_en, reg_clr, output_en: std_logic := '0'; signal data_in_sync: std_logic_vector(7 downto 0) := (others=>'0'); constant clk_period: time := 100ns; -- 10MHz clock begin uut : SCI_transmitter_datapath PORT MAP( clk => clk, data_in_sync=> data_in_sync, load_en=> load_en, reg_clr=> reg_clr, output_en=>output_en, data_out=>data_out); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin load_en<='1'; -- allows shift register to receive the data wait for 1*clk_period; data_in_sync<="11111111"; wait for 1*clk_period; load_en<='0'; wait for 1*clk_period; 54
  • 56. reg_clr<='1'; -- clears the shift register wait for 1*clk_period; reg_clr<='0'; wait for 1*clk_period; data_in_sync<="10101010"; wait for 1*clk_period; load_en<='1'; -- allows shift register to receive the data wait for 1*clk_period; -- shift register must be 11001100 load_en<='0'; -- cannot receive data anymore wait for 1*clk_period; data_in_sync<="11111111"; wait for 1*clk_period; -- tries adding new value, but shift enable signal is not on, so shift register must keep its value output_en<='1'; -- output what is on the shift register wait for 8*clk_period; output_en<='0'; wait for 1*clk_period; end process; end testbench; d. Shell i. code library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity SCI_Transmitter_top is Port ( clk : in STD_LOGIC; receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); done_tick: in std_logic; transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2 end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end SCI_Transmitter_top; architecture Behavioral of SCI_Transmitter_top is component SCI_transmitter_controller IS PORT ( clk : in STD_LOGIC; --10 MHz clock data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from flop synchronizer done_tick : in STD_LOGIC; -- from controller of receiver; indicates that new 8bit data is ready load_en : out STD_LOGIC; -- send to datapath reg_clr : out STD_LOGIC; -- send to datapath output_en : out STD_LOGIC; -- send to datapath 55
  • 57. end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end component; component SCI_transmitter_datapath IS PORT ( clk : in STD_LOGIC; --10 MHz clock data_in_sync : in STD_LOGIC_VECTOR(7 downto 0); -- 8bit signal (parallel data) from flop synchronizer load_en : in STD_LOGIC; -- receiveing from controller reg_clr : in STD_LOGIC; -- receiveing from controller output_en : in STD_LOGIC; -- receiveing from controller transmitter_data_out : out STD_LOGIC);-- 1 bit signal to AD2 end component; component SCI_transmitter_double_flop IS PORT ( clk : in STD_LOGIC; --10MHz clock receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); -- 8bit signal from SCI receiver receiver_data_sync :out STD_LOGIC_VECTOR(7 DOWNTO 0)); -- 8bit signal after being delayed by 2 clk cycles end component; signal load_en,reg_clr,output_en: STD_LOGIC :='0'; signal data_in_sync,receiver_data_sync :std_logic_vector(7 downto 0):=(others=>'0'); begin uut4 : SCI_Transmitter_controller port map( clk=>clk, --10 MHz clock data_in_sync =>receiver_data, -- 8bit signal (parallel data) from flop synchronizer done_tick =>done_tick , -- from controller of receiver; indicates that new 8bit data is ready load_en=>load_en, -- send to datapath reg_clr=>reg_clr, -- send to datapath output_en=>output_en, -- send to datapath end_tick =>end_tick);-- indicates finished passing the data to AD2 uut5: SCI_Transmitter_datapath port map ( clk => clk, --10 MHz clock data_in_sync => receiver_data, -- 8bit signal (parallel data) from flop synchronizer load_en =>load_en, -- receiveing from controller reg_clr =>reg_clr, -- receiveing from controller output_en =>output_en, -- receiveing from controller transmitter_data_out =>transmitter_data_out);-- 1 bit signal to AD2 uut3: SCI_Transmitter_double_flop port map ( clk => clk, --10MHz clock 56
  • 58. receiver_data =>receiver_data, -- 8bit signal from SCI receiver receiver_data_sync=>receiver_data_sync); -- 8bit signal after being delayed by 2 clk cycles end Behavioral; ii. testbench library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity SCI_Transmitter_top_tb is end SCI_Transmitter_top_tb; architecture Testbench of SCI_Transmitter_top_tb is component SCI_Transmitter_top is Port ( clk : in STD_LOGIC; receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); done_tick: in std_logic; transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2 end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end component; signal clk : std_logic := '0'; signal transmitter_data_out, done_tick : std_logic:= '0'; signal receiver_data: std_logic_vector(7 downto 0):= (others => '0'); signal end_tick :std_logic :='0'; constant clk_period : time := 100ns; -- 10 MHz clock -- Data definitions BEGIN uut00: SCI_Transmitter_top port map ( clk => clk, receiver_data=> receiver_data,-- 1bit signal from AD2; done_tick=> done_tick, end_tick => end_tick, transmitter_data_out => transmitter_data_out);-- 8 bits of parallel data -- Clock process definitions clk_process :process begin clk <= '0'; wait for clk_period/2; clk <= '1'; wait for clk_period/2; end process; stim_proc: process begin 57
  • 59. done_tick<='1'; receiver_data<="01010100"; wait for 1*clk_period; done_tick<='0'; wait for 10420*clk_period; done_tick<='1'; receiver_data<="00000000"; wait for 1*clk_period; done_tick<='0'; wait for 10420*clk_period; done_tick<='1'; receiver_data<="10010001"; wait for 1*clk_period; done_tick<='0'; wait for 10420*clk_period; wait for 400*clk_period; end process; end Testbench; 3. Check Character i. code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY check_character IS PORT ( clk : in STD_LOGIC; --2MHz master clock Data_in_receiver : in STD_LOGIC_VECTOR(7 downto 0); --from sci receiver read_en : out std_logic); end check_character; architecture behaviour of check_character is begin process(clk) BEGIN read_en<='0'; if rising_edge(clk) then if Data_in_receiver="00001010" then --ascii code of enter read_en<='1'; else read_en<='0'; end if ; 58
  • 60. end if; end process; end behaviour; ii. testbench library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity check_character_tb is end check_character_tb ; architecture testbench of check_character_tb is component check_character is PORT (clk : in STD_LOGIC; --10MHz master clock Data_in_receiver : in STD_LOGIC_VECTOR(7 downto 0); read_en : out std_logic); end component; signal clk: std_logic; signal Data_in_receiver : std_logic_vector(7 downto 0):="00000000" ; signal read_en : std_logic := '0'; begin uut : check_character PORT MAP( clk => clk, Data_in_receiver => Data_in_receiver, read_en => read_en); clk_proc : process BEGIN CLK <= '0'; wait for 5ns; CLK <= '1'; wait for 5ns; end process clk_proc; stim_proc : process begin Data_in_receiver <= "11110000"; wait for 8 ns; Data_in_receiver <= "00001111"; wait for 8 ns; 59
  • 61. Data_in_receiver <= "10101010"; wait for 8 ns; Data_in_receiver <="00001010"; wait for 8 ns; Data_in_receiver <= "01010101"; wait for 8 ns; Data_in_receiver <= "11110000"; wait for 8 ns; Data_in_receiver <= "00001111"; wait for 8 ns; Data_in_receiver <= "10101010"; wait for 8 ns; Data_in_receiver <="00101010"; wait for 8 ns; Data_in_receiver <= "01010101"; wait for 8 ns; end process stim_proc; end testbench; 4. Buffer i. code library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY Queue IS PORT ( clk : in STD_LOGIC; --10 MHz clock Write_en : in STD_LOGIC; --input character read_en : in STD_LOGIC; --enter pressed done_translating: in std_logic; --Done translating a character to input a new one Data_in_Q : in STD_LOGIC_VECTOR(7 downto 0); Data_out_Q: out STD_LOGIC_VECTOR(7 downto 0); full: out std_logic); end Queue; architecture behavior of Queue is 60
  • 62. type regfile is array(0 to 100) of STD_LOGIC_VECTOR(7 downto 0); signal Queue_reg : regfile; signal W_ADDR : integer := 0; signal R_ADDR : integer := 0; signal used,count: integer := 0; signal full_sig : std_logic; constant threshold: integer := 101; BEGIN process(clk,write_en,read_en,data_in_Q,done_translating) begin if rising_edge(clk) then if (Write_en = '1') and read_en='0' then --if a new character is inputted if (full_sig = '0') then --if the queue is not full Queue_reg(W_ADDR) <= Data_in_Q; --stores data in the queue used<=used+1; count<=count+1; if W_ADDR =threshold-1 then --if the queue is full and we can no longer write, reset the address back to zero W_ADDR <= 0; used<=0; count<=0; else W_ADDR <= W_ADDR + 1; --otherwise, increment the address to store data in the queue end if; end if; end if; if (read_en = '1') then -- if enter is pressed if done_translating='1' then --and if the previous charcter is already transalted by the interpreter to its morse code Queue_reg(R_ADDR) <= (others => '0'); --after it reads whatever is in the address, it resets it back to zero used<=used-1; -- and decrement the number of used levels by one if R_ADDR = threshold-1 then R_ADDR <= 0; used<=0; else R_ADDR <= R_ADDR + 1; end if; end if; end if; end if; 61
  • 63. Data_out_Q <= Queue_reg(R_ADDR); --the queue is reading the stored data and outputting it end process; full_proc: process(count,clk) begin if rising_edge(clk) then if count=threshold-1 then --if the number of used levels is equal to the full size of the queue full_sig<='1'; --full signal becomes high else full_sig<='0'; end if; end if; end process; full <= full_sig; --the signal will light up an LED to tell the user that the queue is full end behavior; ii. testbench library IEEE; use IEEE.std_logic_1164.all; entity Queue_tb is end Queue_tb; architecture testbench of Queue_tb is component Queue IS PORT ( clk : in STD_LOGIC; --10 MHz clock Write_en : in STD_LOGIC; read_en : in STD_LOGIC; done_translating : in STD_LOGIC; Data_in : in STD_LOGIC_VECTOR(7 downto 0); full: out std_logic; Data_out: out STD_LOGIC_VECTOR(7 downto 0)); end component; signal clk : STD_LOGIC; --10 MHz clock signal Write_en : STD_LOGIC := '0'; signal Read_en : STD_LOGIC := '0'; signal done_translating: STD_LOGIC := '0'; signal full : std_logic :='0'; signal Data_in : STD_LOGIC_Vector(7 downto 0) := "00000000"; signal Data_out: STD_LOGIC_Vector(7 downto 0) := "00000000"; 62
  • 64. begin uut : Queue PORT MAP( clk => CLK, Read_en => Read_en, Write_en => Write_en, Data_in => Data_in, full => full, done_translating=>done_translating, Data_out => Data_out); clk_proc : process BEGIN CLK <= '0'; wait for 5ns; CLK <= '1'; wait for 5ns; END PROCESS clk_proc; stim_proc : process begin write_en<= '0'; read_en<= '0'; wait for 8 ns; write_en<='1'; wait for 30 ns; Data_in <= "00000000"; wait for 5 ns; Data_in <= "00000001"; wait for 5 ns; Data_in <= "00000010"; wait for 5 ns; Data_in <= "00000100"; wait for 5 ns; Data_in<= "00001000"; wait for 5 ns; Data_in <= "00010000"; 63
  • 65. wait for 10 ns; write_en<='0'; wait for 5 ns; read_en<='1'; done_translating<='1'; wait for 15 ns; write_en<='1'; wait for 8 ns; Data_in <= "10000000"; wait for 5 ns; Data_in <= "11000000"; wait for 5 ns; Data_in <= "11100000"; wait for 5 ns; Data_in <= "11110000"; wait for 5 ns; Data_in<= "11111000"; wait for 5 ns; Data_in<= "11111100"; wait for 5 ns; Data_in<= "11111110"; wait for 5 ns; done_translating<='1'; wait for 8 ns; Data_in<= "11111110"; wait for 8 ns; Data_in<= "11111111"; wait for 8 ns; wait; end process stim_proc; end testbench; 5. Morse Translator i. code 64
  • 66. library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY translator IS PORT ( clk : in STD_LOGIC; --10MHz master clock Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0); --from buffer done : out STD_LOGIC; Morse_code: out STD_LOGIC_VECTOR(9 downto 0)); end translator; architecture behaviour of translator is BEGIN process(Data_out_buffer) begin done<= '0'; case Data_out_buffer is when "01000001" => Morse_code <= "0111000000"; --A done<='1'; when "01000010" => Morse_code <= "1101010100"; --B done<='1'; when "01000011" => Morse_code <= "1101110100"; --C done<='1'; when "01000100" => Morse_code <= "1101010000"; --D done<='1'; when "01000101" => Morse_code <= "0100000000"; --E done<='1'; when "01000110" => Morse_code <= "0101110100"; --F done<='1'; when "01000111" => Morse_code <= "1111010000"; --G done<='1'; when "01001000" => Morse_code <= "0101010100"; --H done<='1'; when "01001001" => Morse_code <= "0101000000"; --I done<='1'; when "01001010" => Morse_code <= "0111111100"; --J done<='1'; when "01001011" => Morse_code <= "1101110000"; --K done<='1'; when "01001100" => Morse_code <= "0111010100"; --L done<='1'; when "01001101" => Morse_code <= "1111000000"; --M done<='1'; when "01001110" => Morse_code <= "1101000000"; --N done<='1'; when "01001111" => Morse_code <= "1111110000"; --O done<='1'; when "01010000" => Morse_code <= "0111110100"; --P done<='1'; 65
  • 67. when "01010001" => Morse_code <= "1111011100"; --Q done<='1'; when "01010010" => Morse_code <= "0111010000"; --R done<='1'; when "01010011" => Morse_code <= "0101010000"; --S done<='1'; when "01010100" => Morse_code <= "1100000000"; --T done<='1'; when "01010101" => Morse_code <= "0101110000"; --U done<='1'; when "01010110" => Morse_code <= "0101011100"; --V done<='1'; when "01010111" => Morse_code <= "0111110000"; --W done<='1'; when "01011000" => Morse_code <= "1101011100"; --X done<='1'; when "01011001" => Morse_code <= "1101111100"; --Y done<='1'; when "01011010" => Morse_code <= "1111010100"; --Z done<='1'; when "00000000" => Morse_code <= "1111111111"; --0 done<='1'; when "00000001" => Morse_code <= "0111111111"; --1 done<='1'; when "00000010" => Morse_code <= "0101111111"; --2 done<='1'; when "00000011" => Morse_code <= "0101011111"; --3 done<='1'; when "00000100" => Morse_code <= "0101010111"; --4 done<='1'; when "00000101" => Morse_code <= "0101010101"; --5 done<='1'; when "00000110" => Morse_code <= "1101010101"; --6 done<='1'; when "00000111" => Morse_code <= "1111010101"; --7 done<='1'; when "00001000" => Morse_code <= "1111110101"; --8 done<='1'; when "00001001" => Morse_code <= "1111111101"; --9 done<='1'; when "00100000" => Morse_code <= "0000000000"; --space done<='1'; when "01100001" => Morse_code <= "0111000000"; --a done<='1'; when "01100010" => Morse_code <= "1101010100"; --b done<='1'; when "01100011" => Morse_code <= "1101110100"; --c done<='1'; when "01100100" => Morse_code <= "1101010000"; --d done<='1'; when "01100101" => Morse_code <= "0100000000"; --e 66
  • 68. done<='1'; when "01100110" => Morse_code <= "0101110100"; --f done<='1'; when "01100111" => Morse_code <= "1111010000"; --g done<='1'; when "01101000" => Morse_code <= "0101010100"; --h done<='1'; when "01101001" => Morse_code <= "0101000000"; --i done<='1'; when "01101010" => Morse_code <= "0111111100"; --j done<='1'; when "01101011" => Morse_code <= "1101110000"; --k done<='1'; when "01101100" => Morse_code <= "0111010100"; --l done<='1'; when "01101101" => Morse_code <= "1111000000"; --m done<='1'; when "01101110" => Morse_code <= "1101000000"; --n done<='1'; when "01101111" => Morse_code <= "1111110000"; --o done<='1'; when "01110000" => Morse_code <= "0111110100"; --p done<='1'; when "01110001" => Morse_code <= "1111011100"; --q done<='1'; when "01110010" => Morse_code <= "0111010000"; --r done<='1'; when "01110011" => Morse_code <= "0101010000"; --s done<='1'; when "01110100" => Morse_code <= "1100000000"; --t done<='1'; when "01110101" => Morse_code <= "0101110000"; --u done<='1'; when "01110110" => Morse_code <= "0101011100"; --v done<='1'; when "01110111" => Morse_code <= "0111110000"; --w done<='1'; when "01111000" => Morse_code <= "1101011100"; --x done<='1'; when "01111001" => Morse_code <= "1101111100"; --y done<='1'; when "01111010" => Morse_code <= "1111010100"; --z done<='1'; when others => Morse_code <= "1111111111"; --in case of an invalid input, the output will be a zero done<='1'; end case; end process; end behaviour; 67
  • 69. ii. testbench library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity translator_tb is end translator_tb ; architecture testbench of translator_tb is component translator is PORT ( clk : in STD_LOGIC; --2MHz master clock Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0); --from buffer done : out STD_LOGIC; Morse_code: out STD_LOGIC_VECTOR(9 downto 0)); end component; signal clk: std_logic; signal Data_out_buffer: std_logic_vector(7 downto 0) :="00000000"; signal done: std_logic :='0'; signal Morse_code: std_logic_vector(9 downto 0) :="0000000000"; begin uut : translator PORT MAP( clk => clk, data_out_buffer => data_out_buffer, Morse_code => Morse_code, done =>done); clk_proc : process BEGIN CLK <= '0'; wait for 5ns; CLK <= '1'; wait for 5ns; end process clk_proc; stim_proc : process begin Data_out_buffer<="01001000"; wait for 20 ns; Data_out_buffer<="01100101"; wait for 20 ns; Data_out_buffer<="01101100"; wait for 20 ns; 68
  • 70. Data_out_buffer<="01101100"; wait for 20 ns; Data_out_buffer<="01001111"; wait for 20 ns; Data_out_buffer<="10101010"; --random number wait for 20 ns; wait; end process stim_proc; end testbench; 6. Morse Interpreter a. Controller i. code -- Code your design here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY morse_interpreter_controller IS PORT ( clk : in STD_LOGIC; -- 10 MHz clk translation_done : in STD_LOGIC; -- indicates new character is ready space: in STD_LOGIC; -- from datapath not_space: in STD_LOGIC; -- from datapath dot: in STD_LOGIC; -- from datapath dash: in STD_LOGIC; -- from datapath end_char: in STD_LOGIC; -- from datapath load_en : out STD_LOGIC; -- send to datapath shift_en : out STD_LOGIC; -- send to datapath check_bits_en: out STD_LOGIC; -- send to datapath count_T_en: out STD_LOGIC; -- send to datapath count_3T_en: out STD_LOGIC; -- send to datapath count_7T_en: out STD_LOGIC; -- send to datapath end_trans : out STD_LOGIC);-- indicates the translation is over end morse_interpreter_controller; architecture behavior of morse_interpreter_controller is --Signals type state_type is (idle, shift_register, shift_bits, check_bits, clear, time_3T, time_T, time_7T, time_within_letter, time_between_letters); -- states of FSM 69
  • 71. signal current_state, next_state : state_type := idle; signal count_7T, count_3T, count_T, count_within_char, count_between_letters: integer:=0; -- count the time between works and characters signal count_between_letters_TC, count_T_TC, count_3T_TC, count_7T_TC, count_within_char_TC: std_logic:='0'; signal count_3T_en_signal, count_T_en_signal, count_7T_en_signal, count_within_char_en, count_between_letters_en : std_logic:='0'; BEGIN -- update state machine states stateUpdate: process(clk) BEGIN if rising_edge(clk) then current_state <= next_state; end if; end process stateUpdate; -- CONTROLLER controller: process (current_state, translation_done, space, not_space, dot, dash, end_char, count_3T_TC, count_T_TC, count_7T_TC,count_T,count_within_char_TC, count_between_letters_TC) begin -- defaults; will only change inside the states count_T_en_signal<='0'; count_3T_en_signal<='0'; count_7T_en_signal<='0'; count_within_char_en<='0'; count_between_letters_en<='0'; load_en<='0'; shift_en<='0'; check_bits_en<='0'; count_3T_en<='0'; count_7T_en<='0'; count_T_en<='0'; end_trans<='0'; case (current_state) is when idle=> if translation_done='1' then -- ready to receive new bits next_state<=shift_register; end if; when shift_register=> load_en<='1'; -- enables to load data into a register if space='1' then -- if the character is a space next_state<=time_7T; -- waits for 7T elsif not_space='1' then next_state<=check_bits; --waits for 3T end if; 70
  • 72. when time_between_letters=> count_between_letters_en<='1'; if count_between_letters_TC = '1' then -- after waited 3T next_state<= clear; end if; when shift_bits=> shift_en<='1'; -- enables to left shift the bits next_state<= check_bits; when check_bits=> check_bits_en<='1'; if dot='1' then next_state<= time_T; -- dot elsif dash='1' then next_state<= time_3T; -- dash end if; if end_char='1' then next_state<= time_between_letters; -- end of chacracter end if; when time_within_letter=> -- time between dots and dashes count_within_char_en<='1'; if count_within_char_TC = '1' then -- after waited T (1000000) next_state<= shift_bits; end if; when time_3T=> count_3T_en<='1'; count_3T_en_signal<='1'; if count_3T_TC = '1' then -- after waited 3T (3000000) next_state<= time_within_letter; end if; when time_T=> count_T_en<='1'; count_T_en_signal<='1'; if count_T_TC = '1' then -- after waited T (1000000) next_state<= time_within_letter; end if; when time_7T=> count_7T_en<='1'; count_7T_en_signal<='1'; if count_7T_TC = '1' then -- after waited 7T (7000000) next_state<= clear; end if; when clear=> 71
  • 73. end_trans<='1'; next_state<=idle; when others=> -- deals with other cases next_state<=idle; end case; end process; -- WAITING TIME FOR MORSE CODE time_within_char: process(clk, count_within_char_en) begin if rising_edge(clk) then if count_within_char_en = '1' then count_within_char<= count_within_char+1; if count_within_char= 999999 then count_within_char_TC<='1'; else count_within_char_TC<='0'; end if; else count_within_char <= 0; -- zero the counter end if; end if; end process; time_Between_two_letters: process(clk, count_between_letters_en) begin if rising_edge(clk) then if count_between_letters_en = '1' then count_between_letters<= count_between_letters+1; if count_between_letters= 999999 then count_between_letters_TC<='1'; else count_between_letters_TC<='0'; end if; else count_between_letters <= 0; -- zero the counter end if; end if; end process; wait_time_T: process (clk, count_T_en_signal) begin if rising_edge(clk) then if count_T_en_signal='1' then -- in time_T state count_T<=count_T+1; if count_T = 999999 then count_T_TC <= '1'; else 72
  • 74. count_T_TC<='0'; end if; end if; if count_T_en_signal ='0' then -- zero the counter count_T<=0; end if; end if; end process; wait_time_3T: process (clk, count_3T_en_signal) begin if rising_edge(clk) then if count_3T_en_signal='1' then -- in time_3T state count_3T<=count_3T+1; if count_3T = 2999999 then count_3T_TC <= '1'; else count_3T_TC<='0'; end if; end if; if count_3T_en_signal ='0' then -- zero the counter count_3T<=0; end if; end if; end process; wait_time_7T: process (clk, count_7T_en_signal) begin if rising_edge(clk) then if count_7T_en_signal='1' then -- in time_7T state count_7T<=count_7T+1; if count_7T = 5999999 then count_7T_TC <= '1'; else count_7T_TC<='0'; end if; end if; if count_7T_en_signal='0' then -- zero the counter count_7T<=0; end if; end if; end process; end behavior; ii. testbench library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; 73
  • 75. entity morse_interpreter_controller_tb is end morse_interpreter_controller_tb; architecture testbench of morse_interpreter_controller_tb is component morse_interpreter_controller PORT ( clk : in STD_LOGIC; -- 10 MHz clk translation_done : in STD_LOGIC; -- indicates new character is ready space: in STD_LOGIC; -- from datapath not_space: in STD_LOGIC; -- from datapath dot: in STD_LOGIC; -- from datapath dash: in STD_LOGIC; -- from datapath end_char: in STD_LOGIC; -- from datapath load_en : out STD_LOGIC; -- send to datapath shift_en : out STD_LOGIC; -- send to datapath check_bits_en: out STD_LOGIC; -- send to datapath count_T_en: out STD_LOGIC; -- send to datapath count_3T_en: out STD_LOGIC; -- send to datapath count_7T_en: out STD_LOGIC; -- send to datapath end_trans : out STD_LOGIC);-- indicates the translation is over -- signals end component; signal clk, dot, dash, end_char, translation_done, space, not_space, load_en, shift_en, check_bits_en, end_trans,count_T_en,count_3T_en,count_7T_en: std_logic := '0'; constant clk_period: time := 100ns; -- 10MHz clock begin uut : morse_interpreter_controller PORT MAP( clk => clk, translation_done=> translation_done, space=> space, not_space=>not_space, dot=> dot, dash=> dash, end_char=>end_char, load_en=>load_en, shift_en=>shift_en, check_bits_en=>check_bits_en, count_T_en=> count_T_en, count_3T_en=>count_3T_en, count_7T_en=> count_7T_en, end_trans=>end_trans); 74
  • 76. clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin -- testing for space case wait for 5*clk_period; translation_done<= '1'; -- ready to receive new character wait for 1*clk_period; translation_done<= '0'; wait for 1*clk_period; space<='1'; wait for 70*clk_period; space<='0'; wait for 70*clk_period; -- testing for other characters wait for 5*clk_period; translation_done<= '1'; -- ready to receive new character wait for 1*clk_period; translation_done<= '0'; wait for 1*clk_period; not_space<='1'; wait for 30*clk_period; not_space<='0'; dot<='1'; wait for 10*clk_period; dot<='0'; wait for 10*clk_period; dash<='1'; wait for 30*clk_period; dash<='0'; wait for 10*clk_period; end_char<='1'; wait for 50*clk_period; end_char<='0'; wait for 1*clk_period; end process; end testbench; b. Datapath i. Code -- Code your design here library IEEE; 75
  • 77. use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; ENTITY morse_interpreter_datapath IS PORT ( clk : in STD_LOGIC; --10 MHz clock translation_done: in std_logic; -- coming from translator; indicates a new character was converted to morse code morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal count_T_en : in STD_LOGIC; -- from controller count_3T_en : in STD_LOGIC; -- from controller count_7T_en : in STD_LOGIC; -- from controller load_en : in STD_LOGIC; -- from controller shift_en : in STD_LOGIC; -- from controller check_bits_en : in STD_LOGIC; -- from controller space : out STD_LOGIC; -- send to controlller no_space : out STD_LOGIC; -- send to controlller dot : out STD_LOGIC; -- send to controlller dash : out STD_LOGIC; -- send to controlller end_char : out STD_LOGIC; -- send to controlller sound : out STD_LOGIC; light : out STD_LOGIC); end morse_interpreter_datapath; architecture behavior of morse_interpreter_datapath is -- signal signal reg: std_logic_vector(9 downto 0):= (others=>'0');-- holds 10 bits of data signal fill_reg: std_logic_vector(1 downto 0):= "00"; -- used to left shift bits out of the register BEGIN -- DATAPATH translation: process (clk, translation_done, load_en, morse_in, shift_en, check_bits_en) begin if rising_edge(clk) then --if translation_done = '1' then -- gets new morse code if load_en='1' then -- enables morse code to be saved in the register reg<= morse_in; -- register gets the morse code value if morse_in = "0000000000" then -- if the character is a space space<='1'; -- flags we received a space no_space<='0'; else no_space<='1'; -- flags we have a regular character space<='0'; end if; 76
  • 78. else space<='0'; no_space<='0'; reg<=reg; -- register gets its current value end if; if shift_en='1' then reg<= reg(7 downto 0)&fill_reg; -- left shifting the bits out of the register end if; if check_bits_en='1' then if reg(9 downto 8)="01" then dot<='1'; -- flags we have a dot dash<='0'; end_char<='0'; elsif reg(9 downto 8)="11" then dash<='1'; -- flags we have a dash dot<='0'; end_char<='0'; elsif reg(9 downto 8)="00" then end_char<='1'; -- flags we reached end othe character dash<='0'; dot<='0'; end if; else dot<='0'; dash<='0'; end_char<='0'; end if; if count_T_en='1' then -- during the time for morse code sound <='1'; light <='1'; elsif count_3T_en='1' then -- during the time for morse code sound <='1'; light <='1'; elsif count_7T_en ='1' then -- during the time for morse code sound <='1'; light <='1'; else sound <='0'; light <='0'; end if; --end if; end if; end process; 77
  • 79. end behavior; ii. testbench -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity morse_interpreter_datapath_tb is end morse_interpreter_datapath_tb; architecture testbench of morse_interpreter_datapath_tb is component morse_interpreter_datapath PORT ( clk : in STD_LOGIC; --10 MHz clock translation_done: in std_logic; -- coming from translator; indicates a new character was converted to morse code morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal count_T_en : in STD_LOGIC; -- from controller count_3T_en : in STD_LOGIC; -- from controller count_7T_en : in STD_LOGIC; -- from controller load_en : in STD_LOGIC; -- from controller shift_en : in STD_LOGIC; -- from controller check_bits_en : in STD_LOGIC; -- from controller space : out STD_LOGIC; -- send to controlller no_space : out STD_LOGIC; -- send to controlller dot : out STD_LOGIC; -- send to controlller dash : out STD_LOGIC; -- send to controlller end_char : out STD_LOGIC; -- send to controlller sound : out STD_LOGIC; light : out STD_LOGIC); end component; -- signals signal clk, check_bits_en, load_en, shift_en, translation_done, count_T_en, count_3T_en, count_7T_en, space, no_space, dot, dash, end_char, sound, light : std_logic := '0'; signal morse_in : std_logic_vector(9 downto 0):= "0000000000"; constant clk_period: time := 100ns; -- 10MHz clock begin uut : morse_interpreter_datapath PORT MAP( clk => clk, translation_done=>translation_done, 78
  • 80. morse_in=> morse_in, count_T_en=>count_T_en, count_3T_en=>count_3T_en, count_7T_en=>count_7T_en, space=>space, load_en=>load_en, check_bits_en=> check_bits_en, shift_en=>shift_en, no_space=>no_space, dot=>dot, dash=>dash, end_char=>end_char, sound=>sound, light=>light); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 1*clk_period; morse_in<="0111010000"; -- 'S' character wait for 1*clk_period; load_en<='1'; -- passes morse code into register wait for 1*clk_period; load_en<='0'; wait for 1*clk_period; check_bits_en<='1'; -- check the first 2 bits wait for 1*clk_period; check_bits_en<='0'; wait for 1*clk_period; shift_en<='1'; -- shifts register to left wait for 1*clk_period; shift_en<='0'; wait for 1*clk_period; check_bits_en<='1'; -- check the next 2 bits wait for 1*clk_period; check_bits_en<='0'; wait for 1*clk_period; count_T_en<='1'; wait for 2*clk_period; 79
  • 81. count_T_en<='0'; wait for 1*clk_period; count_3T_en<='1'; wait for 2*clk_period; count_3T_en<='0'; wait for 1*clk_period; count_7T_en<='1'; wait for 2*clk_period; count_7T_en<='0'; wait for 1*clk_period; translation_done<='0'; wait for 1*clk_period; morse_in<="0000000000"; -- space character load_en<='1'; -- passes morse code into register wait for 1*clk_period; load_en<='0'; wait for 1*clk_period; end process; end testbench; c. Shell i. code library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity morse_interpreter_top is Port ( clk : in STD_LOGIC; -- 10 MHz clk morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal translation_done : in STD_LOGIC; -- indicates new character is ready end_trans: out STD_LOGIC; -- indicates that finished translating one character sound: out STD_LOGIC; light: out STD_LOGIC); end morse_interpreter_top; architecture Behavioral of morse_interpreter_top is 80
  • 82. component morse_interpreter_controller IS PORT ( clk : in STD_LOGIC; -- 10 MHz clk translation_done : in STD_LOGIC; -- indicates new character is ready space: in STD_LOGIC; -- from datapath not_space: in STD_LOGIC; -- from datapath dot: in STD_LOGIC; -- from datapath dash: in STD_LOGIC; -- from datapath end_char: in STD_LOGIC; -- from datapath load_en : out STD_LOGIC; -- send to datapath shift_en : out STD_LOGIC; -- send to datapath check_bits_en: out STD_LOGIC; -- send to datapath count_T_en: out STD_LOGIC; -- send to datapath count_3T_en: out STD_LOGIC; -- send to datapath count_7T_en: out STD_LOGIC; -- send to datapath end_trans : out STD_LOGIC);-- indicates the translation is over end component; component morse_interpreter_datapath IS PORT ( clk : in STD_LOGIC; --10 MHz clock translation_done: in std_logic; -- coming from translator; indicates a new character was converted to morse code morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal count_T_en : in STD_LOGIC; -- from controller count_3T_en : in STD_LOGIC; -- from controller count_7T_en : in STD_LOGIC; -- from controller load_en : in STD_LOGIC; -- from controller shift_en : in STD_LOGIC; -- from controller check_bits_en : in STD_LOGIC; -- from controller space : out STD_LOGIC; -- send to controlller no_space : out STD_LOGIC; -- send to controlller dot : out STD_LOGIC; -- send to controlller dash : out STD_LOGIC; -- send to controlller end_char : out STD_LOGIC; -- send to controlller sound : out STD_LOGIC; light : out STD_LOGIC); end component; signal space,not_space,dot, dash, end_char, load_en, shift_en, check_bits_en, count_T_en, count_3T_en, count_7T_en, no_space: STD_LOGIC :='0'; begin uut_inter : morse_interpreter_controller port map (clk => clk, translation_done=> translation_done, space=> space, not_space=>not_space, dot=> dot, 81
  • 83. dash=> dash, end_char=>end_char, load_en=>load_en, shift_en=>shift_en, check_bits_en=>check_bits_en, count_T_en=> count_T_en, count_3T_en=>count_3T_en, count_7T_en=> count_7T_en, end_trans=>end_trans); uut2_inter: morse_interpreter_datapath PORT MAP( clk => clk, translation_done => translation_done, morse_in=> morse_in, count_T_en=>count_T_en, count_3T_en=>count_3T_en, count_7T_en=>count_7T_en, space=>space, load_en=>load_en, check_bits_en=> check_bits_en, shift_en=>shift_en, no_space=>not_space, dot=>dot, dash=>dash, end_char=>end_char, sound=>sound, light=>light); end Behavioral; ii. testbench library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity morse_interpreter_top_tb is end morse_interpreter_top_tb; architecture Testbench of morse_interpreter_top_tb is component morse_interpreter_top is Port ( clk : in STD_LOGIC; -- 10 MHz clk morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal translation_done : in STD_LOGIC; -- indicates new character is ready 82
  • 84. end_trans: out STD_LOGIC; -- indicates that finished translating one character sound: out STD_LOGIC; light: out STD_LOGIC); end component; signal clk : std_logic := '0'; signal translation_done : std_logic:= '0'; signal morse_in: std_logic_vector(9 downto 0):= (others => '0'); signal end_trans, sound, light :std_logic :='0'; constant clk_period : time := 100ns; -- 10 MHz clock begin uut0_inter_top: morse_interpreter_top port map ( clk => clk, morse_in=> morse_in, translation_done=> translation_done, end_trans => end_trans, sound=> sound, light => light); -- Clock process definitions clk_process :process begin clk <= '0'; wait for clk_period/2; clk <= '1'; wait for clk_period/2; end process; stim_proc: process begin wait for 5*clk_period; morse_in<="0111000000"; translation_done <='1'; wait for 1*clk_period; translation_done <='0'; wait for 15000000*clk_period; morse_in<="0000000000"; translation_done <='1'; wait for 1*clk_period; translation_done <='0'; wait for 8000000*clk_period; wait for 1042*clk_period; end process; end Testbench; 83
  • 85. 7. Square Wave Oscillator a. Code: -- Code your design here library IEEE; use IEEE.std_logic_1164.all; ENTITY square_wave_oscillator IS PORT ( clk : in STD_LOGIC; --10 MHz clock sound_wave : out STD_LOGIC);-- square wave at 500Hz end square_wave_oscillator; architecture behavior of square_wave_oscillator is signal counter, counter_high : integer:=0; signal rate : integer:=999; -- for squarewave at 500Hz (10^6/500) signal twice_rate : integer:=4000; signal initial_sound : std_logic:='0'; begin square_wave: process (clk) begin if rising_edge(clk) then counter<= counter+1; if (counter=rate) then initial_sound<= NOT(initial_sound); counter<=0; -- zeros the counter end if; end if; end process; sound_wave<=initial_sound; end behavior; b. Testbench: -- Code your testbench here library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity square_wave_oscillator_tb is end square_wave_oscillator_tb; architecture testbench of square_wave_oscillator_tb is 84
  • 86. component square_wave_oscillator PORT ( clk : in STD_LOGIC; --10 MHz clock sound_wave : out STD_LOGIC);-- square wave at 500Hz end component; signal clk, sound_wave: std_logic := '0'; constant clk_period: time := 100ns; -- 10MHz clock begin uut_square : square_wave_oscillator PORT MAP( clk => clk, sound_wave=>sound_wave); clkgen_proc: process begin clk <= not(clk); wait for clk_period/2; end process clkgen_proc; stimulus_proc: process begin wait for 1000* clk_period; end process; end testbench; 8. Final MUX library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity final_mux is Port ( sound_wave: in std_logic; --from sound oscillator sound: in std_logic; --from interpreter sound_final: out STD_LOGIC); end final_mux; architecture Behavioral of final_mux is begin wave: process (sound,sound_wave) begin if sound ='1' then if sound_wave='1' then sound_final<='1'; else 85
  • 87. sound_final<='0'; end if; end if; end process; end Behavioral; 9. Final Top Code (Shell File) i. code library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity final_top is port (clk : in STD_LOGIC; data_in : in STD_LOGIC; -- 1bit signal from AD2; sound_final: out STD_LOGIC; end_tick : out STD_LOGIC; Full: out STD_LOGIC; transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2 light: out STD_LOGIC); end final_top; architecture Behavioral of final_top is component SCI_Receiver_top is Port ( clk : in STD_LOGIC; data_in : in STD_LOGIC; -- 1bit signal from AD2; done_tick: out STD_LOGIC; data_out : out STD_LOGIC_VECTOR(7 downto 0));-- 8 bits of parallel data end component; component SCI_Transmitter_top is Port ( clk : in STD_LOGIC; receiver_data : in STD_LOGIC_VECTOR(7 DOWNTO 0); done_tick: in std_logic; transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2 end_tick : out STD_LOGIC);-- indicates finished passing the data to AD2 end component; component morse_interpreter_top is Port ( clk : in STD_LOGIC; -- 10 MHz clk morse_in : in STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal 86
  • 88. translation_done : in STD_LOGIC; -- indicates new character is ready end_trans: out STD_LOGIC; -- indicates that finished translating one character sound: out STD_LOGIC; light: out STD_LOGIC); end component; component Queue IS PORT ( clk : in STD_LOGIC; --10 MHz clock Write_en : in STD_LOGIC; --input character read_en : in STD_LOGIC; --enter pressed done_translating: in std_logic; Data_in_Q : in STD_LOGIC_VECTOR(7 downto 0); Data_out_Q: out STD_LOGIC_VECTOR(7 downto 0); full: out std_logic); end component; component check_character IS PORT ( clk : in STD_LOGIC; --2MHz master clock Data_in_receiver : in STD_LOGIC_VECTOR(7 downto 0); --from sci receiver read_en : out std_logic); end component; component square_wave_oscillator IS PORT ( clk : in STD_LOGIC; --10 MHz clock sound_wave : out STD_LOGIC);-- square wave at 500Hz end component; component translator IS PORT ( clk : in STD_LOGIC; --10MHz master clock Data_out_buffer: in STD_LOGIC_VECTOR(7 downto 0); --from buffer done : out STD_LOGIC; Morse_code: out STD_LOGIC_VECTOR(9 downto 0)); end component; component final_mux is Port ( sound_wave: in std_logic; --from sound oscillator sound: in std_logic; --from interpreter sound_final: out STD_LOGIC); end component; signal done,sound_wave,full,read_en,done_translating,write_en,done_tick,transl ation_done,end_trans,sound : STD_LOGIC; -- 1bit signal from AD2; signal data_out_buffer,data_out, receiver_data,data_in_Q,data_out_Q,data_in_receiver : STD_LOGIC_VECTOR(7 downto 0); 87
  • 89. signal morse_in,morse_code : STD_LOGIC_VECTOR(9 downto 0); -- 10 bit signal encoding morse signal begin uutf1 : SCI_Receiver_top port map(clk =>clk, data_in => data_in, done_tick=>done_tick, data_out =>data_out);-- 8 bits of parallel data uutf2: SCI_Transmitter_top Port map ( clk =>clk, receiver_data =>data_out, done_tick=>done_tick, transmitter_data_out =>transmitter_data_out,-- 1 bit signal to AD2 end_tick => end_tick);-- indicates finished passing the data to AD2 uutf3: check_character Port map ( clk =>clk, --2MHz master clock Data_in_receiver=> data_out, --from sci receiver read_en => read_en); uutf4: Queue Port map ( clk => clk, --10 MHz clock Write_en=> done_tick, --input character read_en =>read_en, --enter pressed done_translating =>end_trans, Data_in_Q=>data_out, Data_out_Q=>data_out_Q, full=>full); uutf5: translator Port map( clk =>clk, --10MHz master clock Data_out_buffer=>data_out_Q, --from buffer done =>done, Morse_code => Morse_code); uutf6: morse_interpreter_top Port map ( clk => clk, -- 10 MHz clk morse_in =>Morse_code, -- 10 bit signal encoding morse signal translation_done =>done, -- indicates new character is ready end_trans=> end_trans,-- indicates that finished translating one character sound=>sound, light=>light); uutf7: square_wave_oscillator PORT map ( clk => clk, --10 MHz clock sound_wave =>sound_wave);-- square wave at 500Hz 88
  • 90. uutf8: final_mux port map (sound_wave =>sound_wave, --from sound oscillator sound=>sound, --from interpreter sound_final=>sound_final); end Behavioral; ii. testbench library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity final_top_tb is end final_top_tb; architecture testbench of final_top_tb is component final_top is port (clk : in STD_LOGIC; data_in : in STD_LOGIC; -- 1bit signal from AD2; sound_final: out STD_LOGIC; end_tick : out STD_LOGIC; Full: out STD_LOGIC; transmitter_data_out : out STD_LOGIC;-- 1 bit signal to AD2 light: out STD_LOGIC); end component; signal clk, data_in,sound_final,end_tick,transmitter_data_out,light : std_logic := '0'; constant clk_period : time := 100ns; -- 10 MHz clock -- Data definitions BEGIN uuttb: final_top port map ( clk => clk, data_in=> data_in, -- 1bit signal from AD2; sound_final =>sound_final, end_tick =>end_tick, transmitter_data_out=>transmitter_data_out,-- 1 bit signal to AD2 light=>light); -- Clock process definitions clk_process :process begin clk <= '0'; wait for clk_period/2; clk <= '1'; wait for clk_period/2; end process; stim_proc: process 89
  • 91. begin data_in<='1'; wait for 10420*clk_period; data_in<='0'; wait for 10420*clk_period; data_in<='1'; wait for 10420*clk_period; data_in<='0'; wait for 10420*clk_period; data_in<='1'; wait for 10420*clk_period; data_in<='1'; wait for 10420*clk_period; data_in<='1'; wait for 10420*clk_period; data_in<='0'; wait for 10420*clk_period; data_in<='0'; wait for 10420*clk_period; data_in<='1'; wait for 10420*clk_period; wait for 400*clk_period; wait; end process; end Testbench; 90