State Machine of Input Controller

advertisement
Structured Digital Design
EEN 316 Section 48
Final Project
Morse Code Translator
Cynthia Rodriguez
Nemanja Stojanovic
Michael Hall
Jia Xu, TA
University of Miami
5 December 2013
Abstract
The Morse Code Translator project is a design that takes inputs of the form “.” and “-”, or
dots and dashes, that correspond to the Morse Alphabet and decodes them into a human
readable symbol, displaying the result on the Seven Segment Display.
The design contains 4 stages:
-
Top level Morse Code unit
-
Control unit that specifies the state machine for decoding Morse code
-
A sequence builder unit
-
An LED Decoder unit
This project was our third choice for the final project for the class, we had had 2 other
ideas prior. Our first idea was a piano decoder that would use a PS/2 keyboard to take
inputs and output a specific sound according to the key that was pressed. After
researching and testing, we came to the conclusion that using Audio Codecs in VHDL
and ModelSim too advanced for us at the current time. Our second idea was to use
keyboard input again to input a letter or Arabic number in Morse Code and the output
would be the decoded code displayed on the seven segment. This idea had to be discarded
due to the fact that the Altera DE2 board has old-fashioned PS/2 ports that communicate
with the keyboard, and we weren’t able to find a PS/2 keyboard that would work. Finally,
we arrived at our final project which would be like the previous idea except without any
external I/O devices, that is, all I/O operations would be done on the DE2 board itself.
The Morse Code Translator was completed successfully, although we had some
synchronization issues that would not give us the desired output when we implemented
the code on a physical device.
1
Table of Contents
Introduction ............................................................................................................................... 3
Objectives .................................................................................................................................... 4
Requirements and Equipment ............................................................................................. 4
Design and Implementation ................................................................................................. 5
Specifications ....................................................................................................................................... 7
Design Synthesis ................................................................................................................................. 7
VHDL Code ................................................................................................................................... 8
Results and Simulations ...................................................................................................... 12
Synthesis ................................................................................................................................... 14
Conclusion ................................................................................................................................ 14
Works Cited ............................................................................................................................. 14
2
Introduction
The Morse Code Translator project is a design that takes Morse Code as dots and dashes
as inputs and decodes it into a symbols we are used to displaying the output on the Seven
Segment Display.
The design contains 4 stages:
-
Top level Morse Code unit
-
Control unit that controls the state machine for decoding Morse code
-
A sequence builder unit
-
A LED Decoder unit
Background:
The Morse Code is a method of transmitting text information as series of on-off tones,
lights, or clicks that can be directly understood by a skilled listener or observer. The
Morse code alphabet has some variations, but the one we will be using will be the official
International Morse Code, provided below:
Morse Code Alphabet
3
In order to accomplish this design, we implemented a top level module that connects the
following three components:
-
Sequence Builder
-
Input Controller/Morse Decoder
-
Led Decoder/Display
The top level module will have 4 input signals that will be input as switches:
1) Start – resets the registers and seven segment
2) Dash – input a dash
3) Dot – input a dot
4) Finish – output the result to the seven-segment LEDs
The state machine will use and combine these signals into a value that represents raw
Morse code. The 4 states for doing its tasks are:
1) Start – reset
2) Gather – pick up the sequence of dots and dashes
3) No Action – used when neither switch is on
4) Done – output the final result to the seven-segments
Objectives
The objective of this project was to design a fully functional translator for Morse Code
that will accepts “dash” and “dot” inputs, decode this series of characters, and display all
the corresponding letters of the English alphabet (A – Z) as well as all of the decimal
digits of the Arab numerals (0 – 9) according to those inputs.
Requirements and Equipment
Equipment/SW used:
Hardware:
Altera DE2 FPGA Board
Software:
ModelSim
4
Quartus
Design and Implementation
Phase 1: Determining the components we will need
The first phase of our project involved the conceptual design of the project.
We based the design of our components on the main operations needed for this project to
be successful. These operations are the following:
-
Reading user input signal
-
Storing user input and storing it into some sort of standard form
-
Decoding this standard form into Seven Segment outputs
Phase 2: Building the components
The first component built was the Sequence Builder unit that takes 4 single-bit inputs
and produces the Morse instruction 4-bit sequence.
The 4 inputs are:
-
Start signal to determine when the user wants to begin inputting the Morse
code
-
Dash and Dot signals that determine the bit sequence that will represent the
Morse instruction
-
Finish signal that will determine when the user has finished inputting data
This component was very simple but it was fully efficient in formatting user input into a
structure that we can use.
Next, we designed the Input Controller. This component contains the state machine,
both data flow and control portions, that reacts to the user input sequence coming from
the Sequence Builder and stores it into a standardized form that will be decoded for
Seven Segment Display. Since no Morse code instruction in our Data range (A – Z, 0 – 9)
requires more than 5 bits, we decided to make the standardized size of our instruction be
5 bits.
The state machine will have 4 states:
-
Start
5
o This state initializes user input and the needed control and storage
signals to be used during the instruction building process and also
serves as the Clear/Restart state of the whole process.
-
Done
o This state determines the end of user input and the beginning of raw
Morse code (a single letter) decoding process for the Seven Segment
Display.
-
Gather
o This state represents the process of gathering Morse code inputs
(“dots” and “dashes”) and building the 5bit raw Morse code instruction
that will be decoded and sent to the Seven Segment display in the
Done state. The building process of the instruction is done by using a
5-bit shift register to store the input value each time a user sends a dot
(0) or a dash (1). This state also keeps track of the number of bits used
since the size of our Morse code instructions can be from 1bit to 5 bits.
-
No Action
o This state represents the IDLE state of the state machine when we are
not receiving any input from the user and takes care of internal signal
control needed for state machine to function and so that no data gets
corrupted or lost.
Next component was the Seven Segment decoder. This decoder’s purpose was to
receive the raw Morse code instruction from the Input Controller after the user has
finished inputting data and decode this instruction into an appropriate symbol to be
shown on the Seven Segment display. This component also receives the Count signal
from the Input Controller that it uses to determine the number of bits that need to be
decoded.
Phase 3: Connecting the components
This phase involved connecting the three components explained above from a Top-level
component. This component was the Morse Top unit that takes the initial four 1-bit user
input signals (start, dash, dot, finish) from the physical input and outputs the 7-bit Seven
6
Segment data to the physical Seven Segment on the board. This component is in charge
of connecting all of the inner components as well as directly interacting with the user
both from the input and the output side.
Phase 4: Physical I/O
This phase caused us the most problems. The simulations we performed in ModelSim
gave accurate and correct results but we had unexpected glitches that were causing the
data output to behave very chaotically. It took as a fairly long time to decipher what is the
best way to approach this issue. We decided to make the whole project synchronized to
the same clock, as well as add the No Action state to the Input Controller to take care of
any possible data losses. After a few hours of debugging, we have successfully managed
to display the letters C – A – T based on user input of dots and dashes.
Specifications
There were no specifications for this project.
Design Synthesis
7
State Machine of Input Controller:
START
GATHER
NOACTION
DONE
VHDL Code
--Sequence Builder
-----------------------------------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
entity input_build is
port(clk, start, dash, dot, finish : in std_logic;
input_sequence : out std_logic_vector(3 downto 0));
end input_build;
architecture build of input_build is
signal temp_seq: std_logic_vector(3 downto 0);
begin
bld: process(clk)--process(start, dash, dot, finish)
begin
if(clk'event and clk='1') then
temp_seq(3) <= start;
temp_seq(2) <= dash;
temp_seq(1) <= dot;
temp_seq(0) <= finish;
end if;
end process bld;
8
input_sequence <= temp_seq;
end build;
-------------------------------------------------------------------------------------------------------------Input Controller
-----------------------------------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
--Sequence Determinator
entity inputctrl_top is
port ( clk : in std_logic;
input_seq : in std_logic_vector(3 downto 0);
bit_count: out std_logic_vector(2 downto 0);
letter: out std_logic_vector(4 downto 0));
end inputctrl_top;
architecture seqdet of inputctrl_top is
type state_type is (start, gather, noaction, done);
signal state: state_type;
signal shift_reg: std_logic_vector(4 downto 0);
signal count:
std_logic_vector(2 downto 0);
signal raw_morse: std_logic_vector(4 downto 0);
signal input_received: std_logic;
signal sequence_started: std_logic;
begin
--state machine for reading morse code
--input sequence is 4 bits in the MSB order: start dash dot end
--assign: process(input_seq)
assign: process(clk)
--Control Portion-----------------------------------------begin
if(clk'event and clk='1') then
--the start button is pressed (1xxx)
if (input_seq(3)='1') then
state <= start;
-- the finish button is pressed (xxx1)
elsif (input_seq(0)='1') then
state <= done;
--dot or dash is pressed
(x11x)
elsif (input_seq(1)='1' or input_seq(2)='1') then
state <= gather;
--no input is received
(0000)
else
state <= noaction;
end if;
end if;
--Execution Portion---------------------------------------if(clk'event and clk='1') then
case state is
-- start/clr state
when start =>
raw_morse
<= "10101";
shift_reg
<= "00000";
count
<= "000";
input_received <= '0';
sequence_started <= '1';
--will keep on gathering until finish button is pushed
when gather =>
--if input not received and the sequence started
if(input_received = '0' and sequence_started = '1') then
--gather a dash and increment a counter
if
(input_seq = "0100") then
shift_reg <= (shift_reg(3 downto 0) & '1');
count
<= (count + 1);
--gather a dot and increment the counter
--1 means dash
9
elsif (input_seq = "0010") then
shift_reg <= (shift_reg(3 downto 0) & '0');
--0 means dot
count
<= (count + 1);
else
--if input is neither a dot nor a dash, do not change anything
shift_reg(4 downto 0) <= shift_reg(4 downto 0);
count(2 downto 0)
<= count(2 downto 0);
end if;
input_received <= '1';
--set input received signal
end if; --end input received if
--no action state
when noaction =>
shift_reg(4 downto 0) <= shift_reg(4 downto 0);
count(2 downto 0)
<= count(2 downto 0);
raw_morse
<= "10101";
input_received
<= '0'; --reset input received signal
--finish/display state
when done =>
sequence_started <= '0';
case count is
when "001" =>
if (shift_reg = 1) then
raw_morse <= "00001";
--T
--1 elsif (shift_reg = 0) then
raw_morse <= "00000";
--E
--0 .
end if;
when"010"=>
if (shift_reg = 2) then
raw_morse <= "00010";
--N
--10 -.
elsif (shift_reg = 3) then
raw_morse <= "00011";
--M
--11 -elsif (shift_reg = 0) then
raw_morse <= "00000";
--I
--00 ..
elsif (shift_reg = 1) then
raw_morse <= "00001";
--A
--01 .end if;
when "011" =>
if (shift_reg = 3) then
raw_morse <= "00011";
--W
--011 .-elsif (shift_reg = 1) then
raw_morse <= "00001";
--U
--001 ..elsif (shift_reg = 2) then
raw_morse <= "00010";
--R
--010 .-.
elsif (shift_reg = 0) then
raw_morse <= "00000";
--S
--000 ...
elsif (shift_reg = 5) then
raw_morse <= "00101";
--K
--101 -.elsif (shift_reg = 7) then
raw_morse <= "00111";
--O
--111 --elsif (shift_reg = 6) then
raw_morse <= "00110";
--G
--110 --.
elsif (shift_reg = 4) then
raw_morse <= "00100";
--D
--100 -..
end if;
when "100" =>
if (shift_reg = 7) then
raw_morse <= "00111";
--J
--0111 .--elsif (shift_reg = 10)then
raw_morse <= "01010";
--C
--1010 -.-.
elsif (shift_reg = 13)then
raw_morse <= "01101";
--Q
--1101 --.elsif (shift_reg = 0) then
raw_morse <= "00000";
--H
--0000 ....
elsif (shift_reg = 8) then
raw_morse <= "01000";
--B
--1000 -...
elsif (shift_reg = 11)then
raw_morse <= "01011";
--Y
--1011 -.-elsif (shift_reg = 9) then
raw_morse <= "01001";
--X
--1001 -..elsif (shift_reg = 2) then
raw_morse <= "00010";
--F
--0010 ..-.
elsif (shift_reg = 1) then
raw_morse <= "00001";
--V
--0001 ...elsif (shift_reg = 6) then
raw_morse <= "00110";
--P
--0110 .--.
elsif (shift_reg = 4) then
raw_morse <= "00100";
--L
--0100 .-..
elsif (shift_reg = 12)then
raw_morse <= "01100";
--Z
--1100 --..
end if;
when "101" =>
if (shift_reg = 31) then raw_morse <= "11111"; --0
--11111 ----elsif (shift_reg = 15) then raw_morse <= "01111";
--1
--01111 .---elsif (shift_reg = 7) then raw_morse <= "00111"; --2
--00111 ..--elsif (shift_reg = 3) then raw_morse <= "00011"; --3
--00011 ...-elsif (shift_reg = 1) then raw_morse <= "00001"; --4
--00001 ....elsif (shift_reg = 0) then raw_morse <= "00000"; --5
--00000 .....
elsif (shift_reg = 16) then raw_morse <= "10000";
--6
--10000 -....
elsif (shift_reg = 24) then raw_morse <= "11000";
--7
--11000 --...
elsif (shift_reg = 28) then raw_morse <= "11100";
--8
--11100 ---..
elsif (shift_reg = 30) then raw_morse <= "11110";
--9
--11110 ----.
end if;
when others => raw_morse <= "10101"; --this value shuts off the SEVSEG
end case;--end the count case statement
end case;--end the state case statement
end if;--end the clk if statement
end process assign;
letter
<= raw_morse; --send the morse sequence to the SEVSEG decoder
10
bit_count <= count;
end seqdet;
--send the number of bits to SEVSEG to be used for decoding
-------------------------------------------------------------------------------------------------------------Seven Segment Decoder
-----------------------------------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
entity seven_seg is
port (clk: in std_logic;
count: in std_logic_vector(2 downto 0);
letter: in std_logic_vector (4 downto 0);
led: out std_logic_vector(6 downto 0));
end seven_seg;
architecture led_arch of seven_seg is
--signal led: std_logic_vector(6 downto 0);
begin
--inputs are in binary
Translation: process(count, letter, clk)
begin
if(clk'event and clk='1') then
case count is
when "001" =>
if
(letter = 1) then
led <= "1110000"; --t
elsif (letter = 0) then
led <= "0110000"; --E
end if;
when "010" =>
if
(letter = 2) then
led <= "1101010"; --n
elsif (letter = 3) then
led <= "0001001"; --M looks like a big little n
elsif (letter = 0) then
led <= "1101111"; --i
elsif (letter = 1) then
led <= "0001000"; --A
end if;
when "011" =>
if (letter = 3) then led <= "0110110";--W three horizontal bars
elsif (letter = 1) then
led <= "1100011";--u little u
elsif (letter = 2) then
led <= "1111010";--r
elsif (letter = 0) then
led <= "0100100";--S, a 5
elsif (letter = 5) then
led <= "1011000";--k looks like a flipped 4
elsif (letter = 7) then
led <= "1100010";--o
elsif (letter = 6) then
led <= "0000100";--g
elsif (letter = 4) then
led <= "1000010";--d
end if;
when "100" =>
if (letter = 7) then led <= "1000111"; --J 1110001
elsif (letter = 10)then
led <= "1110010"; --c
elsif (letter = 13)then
led <= "0001100"; --q
elsif (letter = 0) then
led <= "1001000"; --H
elsif (letter = 8) then
led <= "1100000"; --b
elsif (letter = 11)then
led <= "1000100"; --y
elsif (letter = 9) then
led <= "1011010"; --X bge light up
elsif (letter = 2) then
led <= "0111000"; --F
elsif (letter = 1) then
led <= "1000001"; --V like a big U
elsif (letter = 6) then
led <= "0011000"; --p
elsif (letter = 4) then
led <= "1110001"; --L
elsif (letter = 12)then
led <= "0010010"; --Z a 2
end if;
when "101" =>
if (letter = 31)then led <= "0000001"; --0
elsif (letter = 15)then
led <= "1001111"; --1
elsif (letter = 7) then
led <= "0010010"; --2
elsif (letter = 3) then
led <= "0000110"; --3
elsif (letter = 1) then
led <= "1001100"; --4
elsif (letter = 0) then
led <= "0100100"; --5
elsif (letter = 16)then
led <= "0100000"; --6
elsif (letter = 24)then
led <= "0001111"; --7
elsif (letter = 28)then
led <= "0000000"; --8
elsif (letter = 30)then
led <= "0000100"; --9
11
end if;
when others => led <= "1111111"; --all off
end case;
--led_out <= led;
end if;
end process Translation;
end led_arch;
-------------------------------------------------------------------------------------------------------------Morse Top Level Unit
-----------------------------------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
entity Morse_top is
port(start, dash, dot, finish, clk: in std_logic;
sev_seg: out std_logic_vector(6 downto 0));
end entity;
architecture morse of Morse_top is
component seven_seg is
port (clk: in std_logic;
count: in std_logic_vector (2 downto 0);
letter: in std_logic_vector (4 downto 0);
led: out std_logic_vector(6 downto 0));
end component;
component inputctrl_top is
port ( clk : in std_logic;
input_seq : in std_logic_vector(3 downto 0);
bit_count: out std_logic_vector(2 downto 0);
letter: out std_logic_vector(4 downto 0));
end component;
component input_build is
port(clk, start, dash, dot, finish : in std_logic;
input_sequence : out std_logic_vector(3 downto 0));
end component;
signal counter : std_logic_vector(2 downto 0);
signal letter : std_logic_vector(4 downto 0);
signal temp_start, temp_dash, temp_dot, temp_f: std_logic;
signal input_seq : std_logic_vector(3 downto 0);
begin
temp_start <= start;
temp_dash <= dash;
temp_dot <= dot;
temp_f
<= finish;
SEQUENCE: input_build
port map(clk, temp_start, temp_dash, temp_dot, temp_f, input_seq);
INPUT: inputctrl_top
port map(clk, input_seq, counter, letter);
SEVSEG: seven_seg
port map(clk, counter, letter , sev_seg);
end architecture;
------------------------------------------------------------------------------------------------------------
Results and Simulations
ModelSim Simulation of inputting Morse Code for the letter ‘T’.
The code is “–” (dash)
12
The output should be:
1110000
As can be seen from the screen shot above, the output for the seven segments when the
Morse Code for ‘T’ was input into the system was 1110000. However, note that the
output took a few clock cycles after the ‘finish’ switch was turned on to appear. This was
reflected in the physical implementation on the code where you had to wait a while
between turning switches on and off. If you changed switches too quickly, the output
would not display correctly or nothing would be displayed at all.
Seven-Segment Decoder:
The above screen shot shows the decoded output to the seven-segment LEDs when the
Morse Code encoded in binary for ‘D’ (dash-dot-dot is 00100 in binary) and ‘M’ (dash –
dash is 00011 in binary) as well as the number of dots and dashes it’s composed of
(count = 3 for D and count = 2 for M) was input. The outputs were correct.
13
Synthesis
Our simulation went through the process of simulating user input and observing the
outcomes in the project after each input.
The user enters the sequence for the letter or number they want then flips the ‘finish’
switch on (make finish = ‘1’) to indicate that they are finished inputting their sequence.
When they want to input a new sequence they flip the ‘start’ switch on (make start = ‘1’)
and this will reset the interior registers and seven-segment LEDs. We also had all-zero
inputs between each individual input to simulate the releasing of the switch, as a user
would do in a real-life demonstration.
Conclusion
Our design takes an input of dashes and dots provided by the user. The leftmost switch on
the DE2 board initializes the input sequence, and the dashes and dots are accepted by the
second and third switches. The fourth switch is flipped when the user is finished inputting
the code. The associated letter or number is displayed on the 7-segment display.
When loading our design on the DE2 board, we need to use the JTAG method.
This does not allow the code to be stored on the board for future use. We need to load the
design onto the board everytime the board becomes reset. Our design is limited because it
needs to be synced to at 4 clock cycles, which was a problem with our original design.
This leads to the realization that the processes we wrote takes more than one clock cycle
to preform, which our original design was designed for.
Works Cited
Morse Code Table - http://www.bbc.co.uk/schools/gcsebitesize/science/images/gatewaysci_09.gif
14
Download