In the course of design, we are exposed to many different kinds of tools that help to develop your design more efficiently and effectively. Throughout this project, we have learned and gained a lot of experience, especially using actmap and designer. In this CAD Tool document, we would like to take this opportunity to share our experiences so that students who take this course in the future would benefit and save more times.
When we start our design, we have so many ideas. If we start to code our design right away, this would lead to so many design errors. Then, we start to draw our state diagram. However, if our design is large and involves many states, drawing it out would take a lot of time. Fortunately, we discover that there is a shareware called "StateCad" that really helps design a lot and reduce a lot of headache.
StateCAD automatically translates bubble diagrams into synthesizable
VHDL, Verilog, ABEL-HDL, Altera-AHDL, and C. Variables, port definitions,
and sensitivity lists are automatically created for all state machines
and associated logic. Because state diagrams are precise and unambiguous,
the resulting HDL is error free and exactly represents your specification.
Revision becomes simple, just fix the graphical diagram and re-compile
to update the HDL.
The following example shows how easy and user-friendly "StateCad" is:
When you finish drawing all the state, just goto File Menu and select HDL Output. Then, it will translate your state into VHDL code. EASY!
If anyone want to download a copy, http://www.statecad.com
Module Name | Area (modules) | Line of VHDL code |
Door Checker | 0 | 32 |
Switch Decoder | 8 | 62 |
LCD Display | 168 | 278 |
Password Checker | 174 | 314 |
Main Controller | 161 | 317 |
Monitor | 21 | 174 |
Total | 532 | 1177 |
Not much! Only 1177 line of code would take up about 97% of the ACT™ 1 FPGA. Therefore, you should think of something reasonable. If you are still not sure, then here comes another important factor "Time". Start your project NOW and finish it early. Then, use "actmapw" to determine the size of your project.
(at the shell, type)
% actmapw &
Later, in the simulation process or back-annotated simulation with extracted delay, you will strongly find that time is the only factor that will make your project success. The reason we say this because "actmap" and "designer" have many constraints on VHDL codes. If you encounter an error and don?t know how to fix it, trial and error is the only solution and this actually helps. Later, we will discuss some errors we meet and how to get around with them.
Procedures
When using procedures, ACTmap VHDL requires the use of intermediate signals. If you have a procedure, the following example will not work:
LCD_procedure(initialize(data));
Add an intermediate signal and try to the following example:
Temp <= initialize(data);
LCD_procedure(Temp);
Multiple Event
If ACTmap complains you with 2 clock, you may probably have 2 or more events within one process. Try to have one event with one process.
The following example won't work:
process(clock,reset) begin
if rising_edge(clock) then
if rising_edge(reset) then
...
...
end if;
end if;
end process;
Modify the code and make reset become one of your states.
change_state : process(clock, reset) begin
if rising_edge(clock) then
if reset = '1' then
state <= reset_state;
else
state <= next_state;
end if;
end if;
state_machine : process(reset, ... ,)
case state is
when reset_state =>
...
when A =>
...
end case;
end process;
Wait and Delay
Do not use wait or delay statements in your VHDL code. ACTmap will not be happy and gives error. The only solution is to explicitly increment a time counter. Please look at Efficient VHDL code under ACTmap for details
Troubles after ACTmap
After you have used ACTmap to generate the .edn file, the chance of likely your file cannot be compiled under designer architecture is very high. It is because ACTmap has added a few characters in the beginning of your VHDL code. Therefore, I recommend that always save your files a second copy (with different names) and use only one copy for ACTmap and use another copy for modification purpose.
The error message will read something like this:
ERROR: near "(" syntax error
ERROR: Quickhdl compilation failed -1-
Graphical Character
After you have coded your project at home, you download it into your account. Later, you start to run your files and compile under ACTmap. Then, strange things happen. This time, ACTmap complains you that your have many "Graphical Character" in your program at some line numbers. However, at these line numbers, you don't see any special characters. Then, you start to be panic and no helps. (This is somewhat similar to my feeling at that time.)
At this time, you have two possible choices. One, re-type the whole program using da and save it with different name. Compile it, again. I believe that this time, ACTmap will not give you the same error messages again (may be some new one :) ) This approach work, but is tedious and very time-consuming. However, we have a better one. We think that from our experience, the reason for this "graphical character" error message is that in the process of transmitting files, some special forms of characters have added to the end of each line. That's why ACTmap reads this special character as "graphical character". This can easily fix using vi editor. (I take lot of time to figure out this) When you open vi editor, type vi at the prompt.
% vi filename.vhd
(Don't worry if you don't know how to use vi)
You will see your filename like below:
library ieee;^M
use ieee.std_logic_1164.all;^M
entity ABC ^M
port ( ... )^M
architecture behavior of something is^M
begin^M
process( ...)^M
statement;^M
end process;^M
end behavior;^M
You whole file has been corrupted with ^M at the end of each line. Then, use your arrow key to go to the ^M position and press x (stands for delete thing at cursor). After you clean up the whole file and run it again using ACTmap. This time, no more "graphical character" error message. Similar idea can be applied if ACTmap or da complains you with some character, which is not inside your file. Try it.
ERROR: Designer : syntax error
After you have converted your file from edn format to VHDL format, you begin to simulate the structural VHDL. If you compile, compiler gives you error message like "Designer: syntax error", this is probably that you have missed the path. Try the following step.
After the above steps, starts design architecture again and re-compiles the structural VHDL file. Hopefully, it doesn?t give you any error.
Script File for Qhsim
When you start simulation, a small change to your VHDL code would need to compile the file again and simulate it again. This requires you to bring up all the signals and initialize them again. Running script file would really help you a lot and save you much time. The following example shows how to write a script file for qhsim:
wave A
wave B
wave clock
force A 0
force B 1
force clock 0 100, 1 200 -r 200
In the qhsim.mod window, type "do init". This will initialize your waveform and save you a lot of time.
Hints for working with back-annotated simulations
We believe that when you are back annotated your design the first time, the chance for your project will work perfectly similar to behaviour simulation is very unlikely. However, don't be panic. Everyone experiences this. Just a reminder that most significant bit (MSB) and the least significant bit (LSB) are reversed. After you recognize this difference, test your design again. If it is still not working, then you have to use step by step approach to debug your program.
Three more hints
when A =>
load_a
<= '1';
s <= "000";
next_state <= B;
when B =>
s <= "011";
next_state <= C;
...
In this case, don't assume at state B, load_a will still remain a value of '1'. Explicitly state it. Therefore, should change to
when B =>
load_a <= '1';
s <= "011";
next_state <= C;
...
This way, you will guarantee your output.
In this course, we have done many things to minimize the modules by actually using different ways to program the same code. Results turn out that actmap doesn't really like the "if " statement, if massive "if" statements have used, this would take lot of modules. See example below:
entity timer is
port (clock, timestart : in std_logic;
time_is_up : out std_logic);
end timer;
architecture time of timer is
begin
timer_logic:
process(clock,timestart)
variable
timecounter : integer := 0;
begin
if (clock = '1' and clock'event) then
if timestart = '1' then
if timecounter < 30 then
timecounter := timecounter + 1;
elsif timecounter = 30 then
time_is_up <= '1';
end if;
elsif timestart = '0' then
timecounter := 0;
time_is_up <= '0';
end if;
end if;
end process;
end time;
This example demonstrates a 30 second-timer (for simplicity, assume
the input clock in 1Hz). This timer will generate a pule for "time_is_up"
when 30 seconds have reached. In this case, we only use "if" statement
in this simple program to show how complex this example can be. The following
is the recorded result under ACTmap using "area" option for map style,
"block" mode, no flatten, "med" effort and max fanout = 16.
Report results
Final Estimated Results
File: t1.edn
Comb. Modules: 131 modules
Area: 197 modules
Longest Path: 191.7 ns
Max Levels: 18
IO Pins: 3
Clk Networks: 1
A simple counter will take 197 modules. Amazing!
entity timer is
port (clock, timestart : in std_logic;
time_is_up : out std_logic);
end timer;
architecture time of timer is
begin
timer_logic: process(clock,timestart)
variable timecounter : integer := 0;
constant timelimit : integer := 30;
begin
if (clock = '1' and clock'event) then
if timestart = '1' then
timecounter := timecounter + 1;
else
timecounter := 0;
end if;
case timecounter is
when timelimit => time_is_up <= '1';
timecounter := 0;
when others => NULL;
end case;
end if;
end process;
end time;
Same compile conditions have been used as above. The result is:
Report results
Final Estimated Results
File: t2_w_case.edn
Comb. Modules: 127 modules
Area: 193 modules
Longest Path: 291.3 ns
Max Levels: 30
IO Pins: 3
Clk Networks: 1
This time, there are only 6 modules different from the above result. Not very much!. The reason is because in this example, only one or two "if" statement has been reduced. If more "if" statements are reduced, this reduces the complexity of your program in compiler sense (at lease, it works for ACTmap). As a result, it reduces the numbers of modules.
See the next example for further reduction in area.
entity timer is
port
(clock, timestart : in std_logic;
time_is_up : out std_logic);
end timer;
architecture time of timer is
type number is range 0 to 31;
begin
timer_logic: process(clock,timestart)
variable timecounter : number := 0;
constant timelimit : number := 30;
begin
if (clock = '1' and clock'event) then
if timestart = '1' then
timecounter := timecounter + 1;
else
timecounter := 0;
end if;
case timecounter is
when timelimit => time_is_up <= '1';
timecounter := 0;
when others => NULL;
end case;
end if;
end process;
end time;
Same compile conditions have been used as above. The result is:
Report results
Final Estimated Results
File: t2_w_type.edn
Comb. Modules: 22 modules
Area: 34 modules
Longest Path: 73.8 ns
Max Levels: 7
IO Pins: 3
Clk Networks: 1
In this example, we have used "type" and "case" statements together. Results have shown a tremendous reduction in area. 159 logic modules reduce. Pretty Amazing The reason for this reduction because ACTmap only uses 6 flip-flops as opposed to 33 flip-flops in the above examples.
One final general comment, start EARLY and don't be too ambitious in project design
Have Fun!
email: dkwok@gpu.srv.ualberta.ca