mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 09:10:10 +00:00
Перенос Implementation steps в Introduction
This commit is contained in:
227
Introduction/Implementation steps.md
Normal file
227
Introduction/Implementation steps.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Этапы реализации проекта в ПЛИС
|
||||
|
||||
Для того, чтобы описанное на **языке описания аппаратуры** устройство было реализовано в ПЛИС, необходимо выполнить несколько этапов:
|
||||
|
||||
1. Элаборацию (elaboration)
|
||||
2. Синтез (synthesis)
|
||||
3. Имплементацию (implementation)
|
||||
4. Генерацию битстрима (generate bitstream)
|
||||
|
||||
Остановимся на каждом шаге подробнее:
|
||||
|
||||
## Elaboration
|
||||
|
||||
На шаге **элаборации**, САПР строит цифровую схему по её **HDL**-описанию. Построенная схема не привязана к конкретной ПЛИС и использует абстрактные элементы: логические вентили, мультиплексоры, элементы памяти и т.п.
|
||||
На самом деле САПР генерирует не схему (картинку, схематик), а так называемый **нетлист**. **Нетлист** — это представление цифровой схемы в виде **графа**, где каждый элемент схемы является **узлом**, а **цепи**, соединяющие эти элементы являются ребрами. **Нетлист** может храниться как в виде каких-то внутренних файлов САПР-а (в случае **нетлиста** для этапа **элаборации**), так и в виде **HDL**-файла, описывающего экземпляры примитивов и связи между ними. Рассмотрим этап **элаборации** и термин **нетлиста** на примере.
|
||||
|
||||
Допустим, мы хотим реализовать следующую цифровую схему:
|
||||
|
||||

|
||||
|
||||
Её можно описать следующим **SystemVerilog**-кодом:
|
||||
|
||||
```SystemVerilog
|
||||
module sample(
|
||||
input logic a, b, c, d, sel,
|
||||
output logic res
|
||||
);
|
||||
|
||||
logic ab = a & b;
|
||||
logic xabc = ab ^ c;
|
||||
|
||||
assign res = sel? d : xabc;
|
||||
|
||||
endmodule
|
||||
```
|
||||
|
||||
Выполним этап **элаборации**. Для этого в **Vivado** на вкладке `RTL Analysis` выберем `Schematic`.
|
||||
|
||||
Откроются следующие окна:
|
||||
|
||||

|
||||
|
||||
В левом окне мы видим наш нетлист. В нижней части обозначены узлы графа (элементы **ab_i**, **res_i**, **xabc_i**, которые представляют собой **И**, **мультиплексор** и **Исключающее ИЛИ** соответственно. Имена этих элементов схожи с именами проводов, присваиванием которым мы создавали данные элементы)
|
||||
|
||||
В верхней части обозначены **ребра графа**, соединяющие элементы схемы. Это входы и выходы нашего модуля, а также созданные нами промежуточные цепи.
|
||||
|
||||
Справа вы видите **схематик** — **графическую схему**, построенную на основе данного **графа** (**нетлиста**).
|
||||
|
||||
## Synthesis
|
||||
|
||||
На шаге синтеза, САПР берет сгенерированную ранее цифровую схему и реализует элементы этой схемы через примитивы конкретной ПЛИС — в основном через логические ячейки, содержащие таблицы подстановки, полный однобитный сумматор и `D-триггер` (см. [как работает ПЛИС](../Introduction/How%20FPGA%20works.md)).
|
||||
|
||||
В рамках нашего примера, САПР смотрит на построенный на этапе **элаборации** **нетлист** и решает, какими средствами (**примитивами**) ПЛИС можно его реализовать. Поскольку схема чисто **комбинационная**, результат её работы можно рассчитать и выразить в виде **таблицы истинности**, а значит для её реализации лучше всего подойдут **Таблицы Подстановки** (**LUT**-ы). Более того, в ПЛИС `xc7a100tcsg324-1` есть пятивходовые LUT-ы, а у нашей схемы именно столько входов. Это означает, работу всей этой схемы можно заменить **всего одной таблицей подстановки** внутри ПЛИС.
|
||||
|
||||
Итак, продолжим рассматривать наш пример и выполним этап синтеза. Для этого нажмем на кнопку `Run Synthesis`.
|
||||
|
||||
После выполнения синтеза у нас появится возможность открыть новый схематик, сделаем это.
|
||||
|
||||

|
||||
|
||||
Мы видим, что между входами/выходами схемы и её внутренней логикой появились новые примитивы — **буферы**. Они нужны, преобразовать уровень напряжения между ножками ПЛИС и внутренней логикой (условно говоря, на вход плис могут приходить сигналы с уровнем `3.3 В`, а внутри ПЛИС примитивы работают с сигналами уровня `1.2 В`).
|
||||
|
||||
Сама же логика, как мы и предполагали, свернулась в одну пятивходовую таблицу подстановки.
|
||||
|
||||
строка `EQN=32'hAAAA3CCC` означает, что таблица подстановки будет инициализирована следующим 32-битным значением: `0xAAAA3CCC`.
|
||||
Поскольку у схемы 5 входов, у нас может быть 2<sup>5</sup>=32 возможных комбинаций входных сигналов и для каждого нужно свое значение результата.
|
||||
|
||||
Можно ли как-то проверить данное 32-битное значение без просчитывания всех 32 комбинаций сигналов "на бумажке"?
|
||||
<details>
|
||||
<summary>
|
||||
Да, можно.
|
||||
</summary>
|
||||
Сперва надо понять в каком именно порядке будут идти эти комбинации. Мы видим, что сигналы подключены к таблице подстановки в следующем порядке: `d, c, b, a, sel`. Это означает, что сама таблица примет вид:
|
||||
|
||||
```ascii
|
||||
|sel| a | b | c | d | |res|
|
||||
|---|---|---|---|---| |---|
|
||||
| 0 | 0 | 0 | 0 | 0 | | 0 |
|
||||
| 0 | 0 | 0 | 0 | 1 | | 0 |
|
||||
| 0 | 0 | 0 | 1 | 0 | | 1 |
|
||||
| 0 | 0 | 0 | 1 | 1 | | 1 |
|
||||
| 0 | 0 | 1 | 0 | 0 | | 0 |
|
||||
....
|
||||
| 1 | 1 | 1 | 1 | 1 | | 1 |
|
||||
```
|
||||
|
||||
Давайте посмотрим на логику исходной схемы и данную таблицу истинности: когда `sel==1`, на выход идет `d`, это означает, что мы знаем все значения для нижней половины таблицы истинности, в нижней половине таблице истинности самый левый входной сигнал (`sel`) равен только единице, значит результат будет совпадать с сигналом `d`, который непрерывно меняется с `0` на `1` и оканчивается значением `1`. Это означает, что если читать значения результатов снизу-вверх (от старших значений к младшим), то сначала у нас будет 16 цифр, представляющих 8 пар `10`:`101010101010`, что эквивалентно записи `AAAA` в шестнадцатиричной записи.
|
||||
|
||||
Рассчитывать оставшиеся 16 вариантов тоже не обязательно, если посмотреть на схему, то можно заметить, что когда `sel!=1`, ни `sel`, ни `d` больше не участвуют в управлении выходом. Выход будет зависеть от операции xor, которая дает `1` только когда её входы не равны между собой. Верхний вход xor (выход И) , будет равен единице только когда входы `a` и `b` равны единице, причем в данный момент, нас интересуют только ситуации, когда `sel!=1`. Принимая во внимание, что в таблице истинности значения входов записываются чередующимися степенями двойки (единицами, парами, четверками, восьмерками) единиц и нулей, мы понимаем, что интересующая нас часть таблицы истинности будет выглядеть следующим образом:
|
||||
|
||||
```ascii
|
||||
...
|
||||
|
||||
| a | b | c |
|
||||
. |---|---|---| .
|
||||
. | 1 | 1 | 0 | .
|
||||
. | 1 | 1 | 0 | .
|
||||
| 1 | 1 | 1 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Только в этой части таблицы истинности мы получим `1` на выходе **И**, при этом в старшей части, вход `c` так же равен `1`. Это значит, что входы **Исключающего ИЛИ** будут равны и на выходе будет `0`. Значит результат этой таблицы истинности будет равен `0011` или `3` в шестнадцатиричной записи.
|
||||
|
||||
Ниже данной части таблицы истинности располагается та часть, где `sel==1`, выше та часть, где выход **И** будет равен `0`. Это означает, что оставшаяся младшая часть будет повторять значения `c`, которое сменяется парами нулей и единиц: `00-11-00-11..`. Эта оставшаяся последовательность будет записана в шестнадцатиричном виде как `0xCCC`.
|
||||
|
||||
Таким образом, мы и получаем искомое выражение `EQN=32'hAAAA3CCC`. Если с этой частью возникли сложности, попробуйте составить данную таблицу истинности (без вычисления самих результатов, а затем просмотрите логику быстрого вычисления результата).
|
||||
</details>
|
||||
|
||||
## Implementation
|
||||
|
||||
После построения новой схемы, где в качестве элементов используются ресурсы конкретной ПЛИС, происходит расчёт размещения этой схемы внутри ПЛИС: выбираются конкретные логические ячейки, происходит маршрутизация сигнала между этими ячейками. Например, реализация 32-битного сумматора с ускоренным переносом может потребовать 32 LUT-а и 8 примитивов вычисления быстрого переноса (`CARRY4`). Будет неразумно использовать для этого примитивы, разбросанные по всему кристаллу ПЛИС, ведь тогда придется выполнять сложную маршрутизацию сигнала, да и временные характеристики устройства так же пострадают (сигналу идущему от предыдущего разряда к следующему придется проходить больший путь). Вместо этого, САПР будет пытаться разместить схему таким образом, чтобы использовались близлежащие примитивы ПЛИС, для получения оптимальных характеристик.
|
||||
|
||||
Что именно считается "оптимальным" зависит от двух вещей: настроек САПР и **ограничений** (**constraints**), наложенных на имплементацию. Ограничения сужают область возможных решений по размещению примитивов внутри ПЛИС под определенные характеристики (временны́е и физические). Например, можно сказать, внутри ПЛИС схема должна быть размещена таким образом, чтобы время прохождения по **критическому пути** не превышало `20ns`. Это временно́е ограничение. Также нужно сообщить САПР, к какой ножке ПЛИС необходимо подключить входы и выходы нашей схемы — это физическое ограничение.
|
||||
|
||||
Ограничения описываются не на языке описания аппаратуры, вместо этого используются текстовые файлы специального формата, зависящего от конкретной САПР.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Пример используемых ограничений для лабораторной по АЛУ.
|
||||
</summary>
|
||||
|
||||
Строки, начинающиеся с `#` являются комментариями.
|
||||
|
||||
Строки, начинающиеся с `set_property` являются физическими ограничениями, связывающими входы и выходы нашей схемы с конкретными входами и выходами ПЛИС.
|
||||
|
||||
Строка `create_clock...` задает временны́е ограничения, описывая целевую тактовую частоту тактового сигнала и его [скважность](https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%B2%D0%B0%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C).
|
||||
|
||||
```xdc
|
||||
## This file is a general .xdc for the Nexys A7-100T
|
||||
|
||||
# Clock signal
|
||||
|
||||
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100 }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
|
||||
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100}];
|
||||
|
||||
# Switches
|
||||
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { SW[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
|
||||
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { SW[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
|
||||
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { SW[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
|
||||
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
|
||||
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
|
||||
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
|
||||
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
|
||||
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
|
||||
set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { SW[8] }]; #IO_L24N_T3_34 Sch=sw[8]
|
||||
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { SW[9] }]; #IO_25_34 Sch=sw[9]
|
||||
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
|
||||
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
|
||||
set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { SW[12] }]; #IO_L24P_T3_35 Sch=sw[12]
|
||||
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SW[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
|
||||
set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { SW[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
|
||||
set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { SW[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15]
|
||||
|
||||
### LEDs
|
||||
|
||||
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
|
||||
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
|
||||
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
|
||||
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
|
||||
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
|
||||
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
|
||||
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
|
||||
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
|
||||
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
|
||||
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
|
||||
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
|
||||
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
|
||||
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
|
||||
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
|
||||
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
|
||||
set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
|
||||
|
||||
## 7 segment display
|
||||
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { CA }]; #IO_L24N_T3_A00_D16_14 Sch=ca
|
||||
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { CB }]; #IO_25_14 Sch=cb
|
||||
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { CC }]; #IO_25_15 Sch=cc
|
||||
set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { CD }]; #IO_L17P_T2_A26_15 Sch=cd
|
||||
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { CE }]; #IO_L13P_T2_MRCC_14 Sch=ce
|
||||
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { CF }]; #IO_L19P_T3_A10_D26_14 Sch=cf
|
||||
set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { CG }]; #IO_L4P_T0_D04_14 Sch=cg
|
||||
# set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { DP }]; #IO_L19N_T3_A21_VREF_15 Sch=dp
|
||||
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
|
||||
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
|
||||
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
|
||||
set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
|
||||
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
|
||||
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
|
||||
set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; #IO_L23P_T3_35 Sch=an[6]
|
||||
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
|
||||
|
||||
## Buttons
|
||||
set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
После выполнения имплементации, нетлист и схема остаются неизменными, однако использованные для реализации схемы примитивы получают свой "адрес" внутри ПЛИС:
|
||||
|
||||

|
||||
|
||||
Теперь, мы можем посмотреть на "внутренности" нашей ПЛИС `xc7a100tcsg324-1` и то, как через её примитивы будет реализована наша схема. Для этого, необходимо отрыть имплементированное устройство: `Implementation -> Open implemented design`. Откроется следующее окно:
|
||||
|
||||

|
||||
|
||||
Может показаться очень страшным и непонятным, но это содержимое ПЛИС. Просто из-за огромного количества содержащихся в ней примитивов, она показана в таком масштабе, что все сливается в один цветной ковер. Большая часть этого окна неактивна (показана в темно-синих тонах) и это нормально, ведь мы реализовали крошечную цифровую схему, она и не должна занимать значительное количество ресурсов ПЛИС.
|
||||
|
||||
Нас интересует "[бледно-голубая точка](https://ru.wikipedia.org/wiki/Pale_Blue_Dot)", расположенная в нижнем левом углу прямоугольника `X0Y1` (выделено красным). Если отмасштабировать эту зону, мы найдем используемый нами LUT:
|
||||
|
||||

|
||||
|
||||
Кроме того, если поиграться со свойствами этого примитива, мы сможем найти нашу таблицу истинности, инициализирующую этот примитив.
|
||||
|
||||
## Generate Bitstream
|
||||
|
||||
После того, как САПР определил конкретные примитивы, их режим работы, и пути сигнала между ними, необходимо создать двоичный файл (**bitstream**), который позволит сконфигурировать ПЛИС необходимым нам образом.
|
||||
Получив этот файл, остается запрограммировать ПЛИС, после чего она воплотит разработанное устройство.
|
||||
|
||||
## Выводы
|
||||
|
||||
Таким образом, маршрут перехода от HDL-описания устройства до его реализации в ПЛИС выглядит следующим образом:
|
||||
|
||||
1. Сперва происходит анализ HDL-описания. В ходе этого анализа выявляются простейшие структуры: регистры, мультиплексоры, вычислительные блоки (сложения/умножения/сдвига и т.п.). Строится граф схемы, построенной с помощью этих структур (**нетлист**). Данный нетлист платформонезависим, т.е. не привязан к конкретной ПЛИС.
|
||||
2. После происходит этап синтеза нетлиста, полученного на предыдущем этапе в нетлист, использующий имеющиеся ресурсы конкретной ПЛИС. Все, использовавшиеся на предыдущем этапе структуры (регистры, мультиплексоры и прочие блоки) реализуются через примитивы ПЛИС (LUT-ы, D-триггеры, блоки сложения и т.п.).
|
||||
3. Затем происходит этап размещения схемы внутри ПЛИС: если на предыдущем этапе часть схемы была реализована через LUT, то на этом этапе решается **какой именно** LUT будет использован. Область допустимых решений по этому вопросу сужается путем наложения **ограничений** (**constraints**).
|
||||
4. После размещения остается только сгенерировать двоичный файл (**bitstream**), который во время прошивки сконфигурирует ПЛИС на реализацию нашей схемы.
|
@@ -8,7 +8,7 @@
|
||||
|
||||
Затем, для того чтобы закрепить понимание происходящего, вам предлагается прочитать документ "[How FPGA Works](./How%20FPGA%20works.md)", рассказывающий о том, как работает ПЛИС изнутри.
|
||||
|
||||
После прочтения второго документа, вам предлагается прочитать документ "[Implementation Steps](../Vivado%20Basics/Implementation%20steps.md)", который был размещен в папке "[Vivado Basics](../Vivado%20Basics/)" поскольку помимо теоретической информации он содержит и практическую информацию по работе с САПР Vivado. Этот документ дополнит ваше понимание о принципе работы ПЛИС и позволит посмотреть на некоторые её реальные элементы изнутри.
|
||||
И в довершение, вам предлагается прочитать документ "[Implementation Steps](./Implementation%20steps.md)". Этот документ дополнит ваше понимание о принципе работы ПЛИС и позволит посмотреть на некоторые её реальные элементы изнутри.
|
||||
|
||||
Обратите внимание, что во втором абзаце не было использовано слово "поймете". Часто это слово несет не тот смысл. Можно прочесть документ и **понять** каждое его слово, но не постигнуть смысла, который в этих слова лежал (**слышать**, но не **слушать**). В романе Роберта Хайнлайна "_Чужок в чужой стране_" вводится особое марсианское слово, непереводимое на земной язык: "**грокать**", которое имеет множество значений. В первом приближении можно подумать, что это слово переводится как "понять", однако это не так. Например, на Марсе очень мало воды и процесс её питья марсианами (по сюжету романа, разумеется) является целым ритуалом, и обозначается этим же словом "грокать". Грокать что-то — означает что это что-то стало частью твоего естества. В отношении информации это означает, это информация стала частью тебя, изменила то как ты думаешь. Грокать — это постичь что-то на самом глубинном уровне, это видеть девушку в красном сквозь завесу падающих зеленых символов. Даже этот абзац расписан для того, чтобы вы не просто поняли что эти документы важно понять — а грокнули то, что эти документы важно грокнуть.
|
||||
|
||||
|
Reference in New Issue
Block a user