⬆️ ⬇️

We do the timer or the first project on the FPGA

I will begin my first article by reporting: in the subject of the article I am a novice myself, but I chose such a topic. I will explain why. I have been reading Habr for quite a long time, and I have always been interested in the topics of those who are currently studying what he is talking about. Such articles are always understandable, always find their audience and always betray the reader’s interest and enthusiasm of the author, which for beginners in any field usually exceeds the limit!



So, recently I became interested in the FPGA theme, faced with them in school, read all sorts of docks and ordered the Starter Kit for experiments. Now, having received a testing ground for experiments by mail and having conducted the first experiment, I am ready to share with habrauser. I hope it will be interesting.



First, let's go over the theory, what does the FPGA abbreviation in the topic of the article mean? You can always read the wiki yourself, so I will try to describe it myself. Who knows what FPGA is, skip boldly.



FPGA (Programmable Logic Integrated Circuit) is one of the types of electronic devices used to implement various logic devices of very different complexity, from binary counters, simple logic circuits (replacing standard integrated circuits - scattering) to specialized processors and neurochips.

')

With the appointment figured out the question - how? Inside the FPGA are some basic elements that are connected based on the configuration record. Possible basic elements, type and location of the configuration record storage depend on the type of FPGA and on the specific model. In modern FPGA there are two types: CPLD and FPGA, we will pay them by paragraph.



CPLD (complex programmable logic device - complex programmable logic devices) - FPGA, the basic elements of which are macrocells and simple logic gates (AND (-NOT) / OR (-NE)). Usually contains less basic elements than FPGA, but is faster. Also usually contains non-volatile configuration memory directly on the chip, but has a limited number of configuration cycles.



FPGA (field-programmable gate array - user-programmable gate array) - FPGA, which usually have a whole bunch of types of basic blocks, these are both custom logic elements (truth tables) and addition-multiplication (Digital signal processing - DSP) and PLL (Phase -Locked Loop) for dividing and multiplying the frequency and some others depending on the model. Usually they have volatile internal memory and functionality for loading configuration from external non-volatile memory.



The definitions of these types of FPGAs and the differences between them can be found very different, both in books and on the Internet. Therefore, you should not dwell on this difference, the producers themselves classify their FPGAs. If you do not remember the abbreviations or understand the meanings of some words - it’s not scary, the main thing is to get a general concept about FPGA, I hope I achieved it. And now to practice!



Let's start by discussing the tools. I will use the Altera Cyclone II FPGA Starter Board developer starter kit, this is a ready-made board on which the Cyclone II FPGA series - EP2C20F484C7N, as well as various peripherals and interfaces are installed. In this article we use LEDs and seven-segment indicators. We will not use any special blocks of this FPGA series, so if you wish, you can use almost any other FPGA (FPGA and CPLD).







Those who are very interested can buy one of the developer’s kits or assemble the device themselves, which is quite difficult for a beginner, but quite a doable task. The programmer circuits and the FPGAs wiring diagrams themselves are easy to googling, and besides, those who previously were engaged in amateur AVR firmware can find a suitable Altera Byte Blaster programmer. In general, I will provide you with a circuit implementation of a habrauzer (At the end of the article, the diagram of my Starter Board) Who wants to try without monetary costs and see the result of the work - you can use the simulator built into Quartus II (this article does not describe how to work with it).



From the software we will use Quartus II, the free version of which you can find on the manufacturer’s website (Altera), both in Windows and Linux versions.



And here we come to practice closely! Launch our CAD system Quartus II and create a project. The first steps of the wizard we specify the name of the project and its place of deployment, then skip the step of adding files (still have time). We will finish creating the project at the stage of choosing a device, if we are doing it on a piece of iron, we know the name of the FPGA for sure, and choose it. If we just do a project for FPGA, we will choose something more powerful, for example, the third cyclone. I choose the FPGA which is installed in my starter whale.



1_proj_wizard_ch




Click Finish - the project is created. The project structure in Quartus is hierarchical, we need to select the top of the hierarchy (Top-Level Entity). We can use for designing circuit files and logic description files on one of the HDL (Hardware description language). My opinion is that the schematic file with the main blocks of logic is most clearly used as the top of the hierarchy, and the blocks themselves are implemented on HDL. Opinions may be different, while choosing, reading a lot of holivarny topics, but while he stopped on such a model, you can make your choice. I chose VHDL ((Very high speed integrated circuits) Hardware Description Language) as the HDL language, you can use any other, for example Verilog or AHDL, it all depends on your preferences.



Create our first project file (File - New ..) and select Block Diagram / Schematic File. Now let's draw the simplest circuit, add one Input, one Output and connect them (in a real FPGA this circuit will transmit a signal from one leg to another). For this Double Click on an empty place of the scheme and in the Symbol dialog that opens, select the required element.



2_add_inp_outp




We connect just like that, by a line. Give the pins the names (Double Click by elements), input call CLOCK_27 [0], and output call LEDR [0]. The names were not chosen by chance - CLOCK_27 [0] I then associate with the generator input 27Mhz, and LEDR [0] with a zero red LED. Save the file, leaving a tick to add to the project. Now set the resulting file to the top of the project hierarchy. To do this, the Project Navigator window, in the Files tab, in the context menu of our file, select Set as Top-Level Entity. Hello, world is ready. Compiling the project (Processing - Start Compilation), if we see Info: Quartus II Full Compilation was successful. - rejoice and believe that the first stage is over.



Now let's deal with our goals. Our device will start counting the minutes and hours when the power is turned on. So we need four seven-segment indicators “HHH: MM”. For timing, we need a more or less accurate 1Hz signal. We get it by dividing the frequency 27Mhz, then we will count it by 60 (seconds), then again by 60 (minutes), and then by 24 (hours). From the last two blocks the binary number of minutes and hours will go to the decoder Bin -> BCD (binary-coded decimal) -> 7seg. Here, in general, and the whole device. At once I will make a reservation that the scheme will be asynchronous (Minutes start from seconds, and hours from minutes), for simplicity and clarity.



3_block_shem




So, we will create our first block - the frequency division block. Create a new file, as we can already, only the file type will be VHDL File. Paste the code into it:



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



entity Div_27Mhz_to_1Hz is

port( clk:in std_logic; clk_out:out std_logic);

end Div_27Mhz_to_1Hz;



architecture div_behavior of Div_27Mhz_to_1Hz is

begin

process(clk)

variable cnt : integer range 0 to 27000000;

begin

if(clk'event and clk = '1')

then



if(cnt >= 13500000)

then

clk_out <= '1';

else

clk_out <= '0';

end if;



if(cnt = 27000000)

then

cnt := 0;

else

cnt := cnt + 1;

end if;



end if;

end process;

end div_behavior;





I will skip the service directives (you can see in the directory, links at the end), I will pay attention only to the logic of work. First we declare the entity, i.e. block itself. We specify its inputs and outputs, their types and names. The std_logic type in common means a bit. Next, we describe the internal architecture of this unit. The architecture consists of parallel processes. Each process has its own sensitivity list, for example, the only process in the example above is sensitive to changes at input clk. Variables can be declared for the process, in our example it is a variable of the type integer range 0 to 27000000. Next, the elementary logic is set in the process body: until half the period has passed - we push the logical zero to the output, half is passed - we push the unit, but do not forget to count and reset the counter to reach 27000000. I do not pretend to the ideal code - while I study, I will be happy with the amendments :)



Save the file with the code and create a symbol (File - Create / Update - Create Symbol Files For Current Files), this is necessary in order to insert this block into our main scheme. You can find your characters in the Project folder in the insert symbol dialog. Now let's go over the remaining blocks in less detail.



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



-- For CONV_STD_LOGIC_VECTOR:

use ieee.std_logic_arith.all;



entity cnt_0_to_59 is

port( clk:in std_logic; c59:out std_logic; vector:out std_logic_vector(5 downto 0));

end cnt_0_to_59;



architecture cnt_behavior of cnt_0_to_59 is

begin

process(clk)

variable cnt : integer range 0 to 59;

begin

if(clk'event and clk = '1')

then

if(cnt = 59)

then

cnt := 0;

c59 <= '1';

vector <= CONV_STD_LOGIC_VECTOR(cnt, 6);

else

cnt := cnt + 1;

c59 <= '0';

vector <= CONV_STD_LOGIC_VECTOR(cnt, 6);

end if;

end if;

end process;

end cnt_behavior;





This is a counting block from zero to 59, which we use to count minutes and seconds. Of the new products, the output type is std_logic_vector (5 downto 0), which defines a group of bits (bit vector), as well as the function CONV_STD_LOGIC_VECTOR (cnt, 6), which converts a variable into a bit vector of the specified length.



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



-- For CONV_STD_LOGIC_VECTOR:

use ieee.std_logic_arith.all;



entity cnt_0_to_23 is

port( clk:in std_logic; vector:out std_logic_vector(4 downto 0));

end cnt_0_to_23;



architecture cnt_behavior of cnt_0_to_23 is

begin

process(clk)

variable cnt : integer range 0 to 23;

begin

if(clk'event and clk = '1')

then

if(cnt = 23)

then

cnt := 0;

vector <= CONV_STD_LOGIC_VECTOR(cnt, 5);

else

cnt := cnt + 1;

vector <= CONV_STD_LOGIC_VECTOR(cnt, 5);

end if;

end if;

end process;

end cnt_behavior;




Above the hour counter. Nothing new.



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



-- For CONV_STD_LOGIC_VECTOR:

use ieee.std_logic_arith.all;



entity bin2bcd_5bit is

port( bin:in std_logic_vector(4 downto 0);

bcd1:out std_logic_vector(3 downto 0);

bcd10:out std_logic_vector(3 downto 0)

);



end bin2bcd_5bit;



architecture converter_behavior of bin2bcd_5bit is

begin

process(bin)

variable i : integer range 0 to 23;

variable i1 : integer range 0 to 9;

begin

i := conv_integer(bin);

i1 := i / 10;

bcd10 <= CONV_STD_LOGIC_VECTOR(i1, 4);

i1 := i rem 10;

bcd1 <= CONV_STD_LOGIC_VECTOR(i1, 4);

end process;

end converter_behavior;




The Binary to BCD converter, in fact, simply splits one binary number into two, each of which represents a digit of a decimal number. Among the novelties is the rem operator, the remainder from division. The converter for six bits is written in a similar way, I will not give it.



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;



entity BCD_to_7seg is

port(

BCD:in std_logic_vector(3 downto 0);

seg:out std_logic_vector(6 downto 0)

);



end BCD_to_7seg;



architecture conv_behavior of BCD_to_7seg is

begin

process(BCD)

begin

if BCD = "0000" then seg <= "0000001";--0

elsif BCD = "0001" then seg <= "1001111";--1

elsif BCD = "0010" then seg <= "0010010";--2

elsif BCD = "0011" then seg <= "0000110";--3

elsif BCD = "0100" then seg <= "1001100";--4

elsif BCD = "0101" then seg <= "0100100";--5

elsif BCD = "0110" then seg <= "0100000";--6

elsif BCD = "0111" then seg <= "0001111";--7

elsif BCD = "1000" then seg <= "0000000";--8

elsif BCD = "1001" then seg <= "0000100";--9

else seg <= "1001001";--err

end if;

end process;

end conv_behavior;




Single-bit converter to a seven-segment code implemented by a simple truth table. The seven-segment code itself is a bit representation of the burning segments on the indicator in the order abcdefg, in my case also inverse.



image




So we implemented all the blocks, it remains to put them together. I will cite the Main scheme and the decoding of the symbol bin2seg, which is also implemented as a scheme to save space.



Main scheme:

(click-click)



(As can be seen in the diagram, I output the seconds count on the green LEDs, again for clarity)



bin2seg:

(click-click)





The project is ready, you can compile and test. I wanted to tell you about the modeling of the work of the scheme in the quarter, but something so happened a lot, there will be interest - I will write in the next article. Now the last stage - we need to associate our virtual inputs / outputs with real FPGA legs.



The association can be carried out after compilation in the menu of Assignments - Pins. In the window that appears, you will see the location of the pins on the chip and under it the list of pins of the project. By changing the Location field, we map the internal inputs to the real legs. In my case, I look at the names of the pins according to the scheme of my board, and in the case of their development you will know the names of the pins. The last step is the firmware, it is carried out from the Tools - Programmer menu, the start button (the programmer must be connected and the drivers are installed).



Well, everything seems to be. In conclusion, I want to say that if there is public interest in this topic, I will certainly write more articles. For example, how to finish this project to normal hours with setting and alarm clock or something new, I already have plans :)







Promised links:

www.altera.com - all kinds of documentation and product advertising

www.bsuir.by/vhdl/reference - VHDL reference

altera.ru - our representative of the company Altera, I ordered a starter kit there

+ I used the book of J.R.Armstrong Modeling of digital systems in the VHDL language.

For those who will undertake to collect himself, I attach the scheme of my board. ( quality )

And also a bonus - the project of the timer ( Kach Kach Kach )

Source: https://habr.com/ru/post/80056/



All Articles