diff --git a/.github/SUMMARY.md b/.github/SUMMARY.md index fc1a624..5d03c73 100644 --- a/.github/SUMMARY.md +++ b/.github/SUMMARY.md @@ -21,6 +21,8 @@ - [Лабораторная №11. Интеграция подсистемы прерываний](Labs/11.%20Interrupt%20integration/README.md) - [Лабораторная №12. Периферийные устройства](Labs/12.%20Peripheral%20units/README.md) - [Лабораторная №13. Программирование](Labs/13.%20Programming/README.md) +- [Лабораторная №14. Программатор](Labs/14.%20Programming%20device/README.md) +- [Лабораторная №15. Оценка производительности](Labs/14.%20Coremark/README.md) --- diff --git a/.pic/Labs/lab_14_programming_device/fig_02.png b/.pic/Labs/lab_14_programming_device/fig_02.png new file mode 100644 index 0000000..46f4673 Binary files /dev/null and b/.pic/Labs/lab_14_programming_device/fig_02.png differ diff --git a/.pic/Labs/lab_14_programming_device/fig_03.drawio.png b/.pic/Labs/lab_14_programming_device/fig_03.drawio.png new file mode 100644 index 0000000..144a411 Binary files /dev/null and b/.pic/Labs/lab_14_programming_device/fig_03.drawio.png differ diff --git a/.pic/Labs/lab_14_programming_device/fig_04.drawio.png b/.pic/Labs/lab_14_programming_device/fig_04.drawio.png new file mode 100644 index 0000000..8e5c4d7 Binary files /dev/null and b/.pic/Labs/lab_14_programming_device/fig_04.drawio.png differ diff --git a/Labs/14. Programming device/README.md b/Labs/14. Programming device/README.md new file mode 100644 index 0000000..4bfbf6f --- /dev/null +++ b/Labs/14. Programming device/README.md @@ -0,0 +1,509 @@ +# Лабораторная работа 14 "Программатор" + +## Цель + +Реализация программатора — части микроконтроллера, обеспечивающего получение программы из внешнего мира. + +## Ход работы + +1. Познакомиться с информацией о программаторах и загрузчиках +2. Изучить информацию о конечных автоматах и способах их реализации +3. Описать перезаписываемую память инструкций +4. Описать и проверить программатор +5. Интегрировать программатор в процессорную систему и проверить её. +6. Проверить работу системы в ПЛИС с помощью предоставленного скрипта по прошивки системы. + +## Теория + +До этого момента, исполняемая процессором программа попадала в память инструкций через магический вызов `$readmemh`. Однако реальные микроконтроллеры не обладают такими возможностями. Программа из внешнего мира попадает в них посредством так называемого **программатора** — устройства, обеспечивающего запись программы в память микроконтроллера. Программатор записывает данные в постоянное запоминающее устройство (ПЗУ). Для того, чтобы программа попала из ПЗУ в память инструкций, после запуска контроллера сперва начинает исполняться **загрузчик** (**bootloader**) — небольшая программа, вшитая в память микроконтроллера на этапе изготовления, которая отвечает за первичную инициализацию и подготовку микроконтроллера к выполнению основной программы (включая её перенос из ПЗУ в память инструкций). + +Со временем появилось несколько уровней загрузчиков: сперва запускается **первичный загрузчик** (**first stage bootloader**, **fsbl**), после которого запускается **вторичный загрузчик** (часто в роли вторичного загрузчика исполняется программа под названием **u-boot**). Такая иерархия загрузчиков может потребоваться например в случае загрузки операционной системы (которая хранится в файловой системе). Код для работы с файловой системой может попросту не уместиться в первичный загрузчик. В этом случае, целью первичного загрузчика является лишь загрузить вторичный загрузчик, который в свою очередь уже будет способен взаимодействовать с файловой системой и загрузить операционную систему[[1]](https://stackoverflow.com/q/22455153). + +Кроме того, код вторичного загрузчика может быть изменен, поскольку программируется вместе с основной программой. Первичный загрузчик может быть изменен не во всех случаях. + +В рамках данной лабораторной работы мы немного упростим процесс передачи программы: вместо записи в ПЗУ, программатор будет записывать её сразу в память инструкций, минуя загрузчик. + +## Практика + +### Конечные автоматы (Finite-State Machines, FSM) + +Программатор будет представлен в виде модуля с [конечным автоматом](https://en.wikipedia.org/wiki/Finite-state_machine). Конечный автомат представляет собой устройство, состоящее из: + +- элемента памяти (так называемого **регистра состояния**); +- логики, обеспечивающей изменение значения **регистра состояния** (логики перехода между состояниями) в зависимости от его текущего состояния и входных сигналов; +- логики, отвечающей за выходы конечного автомата. + +Обычно, конечные автоматы описываются в виде направленного графа переходов между состояниями, где вершины графа — это состояния конечного автомата, а дуги — условия перехода из одного состояния в другое. + +Простейшим примером конечного автомата может быть турникет. Когда приёмник турникета опускается подходящий жетон, тот разблокирует вращающуюся треногу. После попытки поворота треноги, та блокируется до следующего жетона. + +Иными словами, у турникета есть: + +- два состояния + - заблокирован (`locked`) + - разблокирован(`unlocked`) +- два входа + - жетон принят (`coin`) + - попытка поворота треноги (`push`) +- один выход + - блокировка треноги + +Для описания двух состояний нам будет достаточно однобитного регистра. Для взаимодействия с регистром, нам потребуются так же сигнал синхронизации и сброса. + +Опишем данный автомат в виде графа переходов: + +![https://upload.wikimedia.org/wikipedia/commons/9/9e/Turnstile_state_machine_colored.svg](https://upload.wikimedia.org/wikipedia/commons/9/9e/Turnstile_state_machine_colored.svg) + +_Рисунок 1. Граф переходов конечного автомата для турникета[[2]](https://en.wikipedia.org/wiki/Finite-state_machine)._ + +Черной точкой со стрелкой в вершину `Locked` обозначен сигнал сброса. Иными словами, при сбросе турникет всегда переходит в заблокированное состояние. + +Как мы видим, повторное опускание жетона в разблокированном состоянии приводит к сохранению этого состояния (но турникет не запоминает, что было опущено 2 жетона, и после первого же прохода станет заблокирован). В случае попытки поворота треноги в заблокированном состоянии, автомат так и останется в заблокированном состоянии. + +Так же необходимо оговорить приоритет переходов: в первую очередь проверяется попытка поворота треноги, в случае если такой попытки не было, проверяется опускание монетки. Такой приоритет можно было бы указать и на графе, показав на ребрах что переход в состояние unlocked возможен только при отсутствии сигнала `push`. + +### Реализация конечных автоматов в SystemVerilog + +Глядя на описание составляющих конечного автомата, вы могли задаться вопросом: чем автомат отличается от последовательностной логики, ведь она состоит из тех же компонент. Ответом будет: ничем. Конечные автоматы являются математической абстракцией над функцией последовательностной логики[[3]](https://www.allaboutcircuits.com/textbook/digital/chpt-11/finite-state-machines/). Иными словами — конечный автомат, это просто другой способ представления последовательностной логики, а значит вы уже умеете их реализовывать. + +Для реализации регистра состояния конечного автомата будет удобно воспользоваться специальным типом языка **SystemVerilog**, который называется `enum` (**перечисление**). + +Перечисления позволяют объявить объединенный набор именованных констант. В дальнейшем, объявленные имена можно использовать вместо перечисленных значений, им соответствующих. Если не указано иного, первому имени присваивается значение `0`, каждое последующее увеличивается на `1` относительно предыдущего значения. + +```SystemVerilog +module turnstile_fsm( + input logic clk, + input logic rst, + input logic push, + input logic coin, + output logic is_locked +) + + enum logic {LOCKED=1, UNLOCKED=0} state; + + assign is_locked = state; + + always @(posedge clk) begin + if(rst) begin + state <= LOCKED; + end + else begin + if(push) begin + state <= LOCKED; + end + else if (coin) begin + state <= UNLOCKED; + end + else begin + state <= state; + end + end + end +``` + +Кроме того, при должной поддержке со стороны инструментов моделирования, значения объектов перечислений могут выводиться на временную диаграмму в виде перечисленных имен: + +![../../.pic/Labs/lab_14_programming_device/fig_02.png](../../.pic/Labs/lab_14_programming_device/fig_02.png) + +_Рисунок 2. Вывод значений объекта `enum` на временную диаграмму._ + +Для описания регистра состояния часто бывает использовать отдельный комбинационный сигнал, который подается непосредственно на его вход (часто именуемый как `next_state`). Приведенный выше автомат турникета слишком простой, чтобы показать преимущества такого подхода. Предположим, что в момент перехода из состояния `locked` в состояние `unlocked` мы хотим, чтобы загоралась и сразу гасла зеленая лампочка. Без сигнала `next_state` подобный модуль можно было бы описать как: + +```SystemVerilog +module turnstile_fsm( + input logic clk, + input logic rst, + input logic push, + input logic coin, + output logic is_locked, + output logic green_light +) + + enum logic {LOCKED=1, UNLOCKED=0} state; + + assign is_locked = state; + + // (!push) && coin — условие перехода в состояние UNLOCKED + assign green_light = (state == LOCKED) && (!push) && coin; + + always @(posedge clk) begin + if(rst) begin + state <= LOCKED; + end + else begin + if(push) begin + state <= LOCKED; + end + else if (coin) begin + state <= UNLOCKED; + end + else begin + state <= state; + end + end + end +``` + +Используя сигнал `next_state`, автомат мог бы быть переписан следующим образом: + +```SystemVerilog +module turnstile_fsm( + input logic clk, + input logic rst, + input logic push, + input logic coin, + output logic is_locked, + output logic green_light +) + + enum logic {LOCKED=1, UNLOCKED=0} state, next_state; + + assign is_locked = state; + + assign green_light = (state == LOCKED) && (next_state == UNLOCKED); + + always_ff @(posedge clk) begin + if(rst) begin + state <= LOCKED; + end + else begin + state <= next_state + end + end + + always_comb begin + if(push) begin + next_state <= LOCKED; + end + else if (coin) begin + next_state <= UNLOCKED; + end + else begin + next_state <= state; + end + end +``` + +На первый взгляд может показаться, что так даже сложнее. Во-первых, появился дополнительный сигнал. Во вторых появился еще один `always`-блок. Однако представьте на секунду, что условиями перехода будут не однобитные входные сигналы, а какие-нибудь более сложные условия. И что от них будет зависеть не один выходной сигнал, а множество как выходных сигналов, так и внутренних элементов памяти помимо регистра состояний. В этом случае, сигнал `next_state` позволит избежать дублирования множества условий. + +Важно отметить, что объектам типа `enum` можно присваивать только перечисленные константы и объекты того же типа. Иными словами `state` можно присваивать значения `LOCKED`/`UNLOCKED` и `next_state`, но нельзя к примеру присвоить `1'b0`. + +## Задание + +Для выполнения данной лабораторной работы необходимо: + +- описать перезаписываемую память инструкций; +- описать модуль-программатор; +- заменить в `riscv_unit` память инструкций на новую, и интегрировать в `riscv_unit` программатор. + +### Перезаписываемая память инструкций + +Поскольку ранее из памяти инструкций можно было только считывать данные, но не записывать их в нее, программатор не сможет записать принятую из внешнего мира программа. Поэтому необходимо добавить в память инструкций порт на запись. Для того, чтобы различать реализации памяти инструкций, данный модуль будет назвать `rw_instr_mem` со следующим прототипом: + +```SystemVerilog +module rw_instr_mem( + input logic clk_i, + input logic [31:0] read_addr_i, + output logic [31:0] read_data_o, + + input logic [31:0] write_addr_i, + input logic [31:0] write_data_i, + input logic write_enable_i +); +``` + +Как вы помните, модуль `instr_mem` отличался от `data_mem` только портом на запись, так что данный модуль будет практически в точности повторять модуль `data_mem` за исключением того, что у этого модуля нет сигнала `req_i` (поскольку память инструкций подключена к процессору в обход системной шины). + +### Программатор + +Необходимо реализовать модуль-программатор, использующий `uart` в качестве интерфейса для обмена данными с внешним миром, интерфейсами для записи в память инструкций и память данных. + +#### Описание модуля + +В основе работы модуля лежит конечный автомат со следующим графом перехода между состояниями: + +![../../.pic/Labs/lab_14_programming_device/fig_03.drawio.png](../../.pic/Labs/lab_14_programming_device/fig_03.drawio.png) + +_Рисунок 3. Граф перехода между состояниями программатора._ + +Условия перехода следующие: + +- `send_fin = ( msg_counter == 0) && !tx_busy` — условие завершения передачи модулем сообщения по `uart_tx`; +- `size_fin = ( size_counter == 0) && !rx_busy` — условие завершения приема модулем размера будущей посылки; +- `flash_fin = (flash_counter == 0) && !rx_busy` — условие завершения приема модулем блока записываемых данных; +- `next_round = (flash_addr != 0) && !rx_busy` — условие записи блока данных через системную шину; + +Ниже представлен прототип модуля с частично реализованной логикой: + +```SystemVerilog +module bluster +( + input logic clk_i, + input logic rst_i, + + input logic rx_i, + output logic tx_o, + + output logic [ 31:0] instr_addr_o, + output logic [ 31:0] instr_wdata_o, + output logic instr_write_enable_o, + + output logic [ 31:0] data_addr_o, + output logic [ 31:0] data_wdata_o, + output logic data_write_enable_o, + + output logic core_reset_o +); + +enum logic [2:0] { + INIT_MSG, + RCV_SIZE, + SIZE_ACK, + FLASH, + FLASH_ACK, + RCV_NEXT_COMMAND, + WAIT_TX_DONE, + FINISH} +state, next_state; + +logic rx_busy, rx_valid, tx_busy, tx_valid; +logic [7:0] rx_data, tx_data; + +logic [5:0] msg_counter; +logic [31:0] size_counter, flash_counter; +logic [3:0] [7:0] flash_size, flash_addr; + +logic send_fin, size_fin, flash_fin, next_round; + +assign send_fin = (msg_counter == 0) && !tx_busy; +assign size_fin = (size_counter == 0) && !rx_busy; +assign flash_fin = (flash_counter == 0) && !rx_busy; +assign next_round = (flash_addr != 0) && !rx_busy; + +localparam INIT_MSG_SIZE = 40; +localparam FLASH_MSG_SIZE = 57; +localparam ACK_MSG_SIZE = 4; + +logic [INIT_MSG_SIZE-1:0][7:0] init_msg; +// ascii-код строки "ready for flash staring from 0xflash_addr\n" +assign init_msg = { 8'h72, 8'h65, 8'h61, 8'h64, 8'h79, 8'h20, 8'h66, 8'h6F, + 8'h72, 8'h20, 8'h66, 8'h6C, 8'h61, 8'h73, 8'h68, 8'h20, + 8'h73, 8'h74, 8'h61, 8'h72, 8'h69, 8'h6E, 8'h67, 8'h20, + 8'h66, 8'h72, 8'h6F, 8'h6D, 8'h20, 8'h30, 8'h78, + flash_addr_ascii, 8'h0a}; + + +logic [7:0] [7:0] flash_size_ascii, flash_addr_ascii; +genvar i; +generate + for(i=0; i < 4; i=i+1) begin + // Разделяем каждый байт flash_size и flash_addr на два ниббла. + // Ниббл — это 4 бита. Каждый ниббл можно описать 16-ричной цифрой. + // Если ниббл меньше 10 (4'ha), он описывается цифрами 0-9. Чтобы представить + // его ascii-кодом, необходимо прибавить к нему число 8'h30 + // (ascii-код символа '0'). + // Если ниббл больше либо равен 10, он описывается буквами a-f. Для его + // представления в виде ascii-кода, необходимо прибавить число 8'h41 + // (ascii-код символа 'a' - 10). + assign flash_size_ascii[i*2] = flash_size[i][3:0] < 4'ha ? flash_size[i][3:0] + 8'h30 : + flash_size[i][3:0] + 8'h57; + assign flash_size_ascii[i*2+1] = flash_size[i][7:4] < 4'ha ? flash_size[i][7:4] + 8'h30 : + flash_size[i][7:4] + 8'h57; + + assign flash_addr_ascii[i*2] = flash_addr[i][3:0] < 4'ha ? flash_addr[i][3:0] + 8'h30 : + flash_addr[i][3:0] + 8'h57; + assign flash_addr_ascii[i*2+1] = flash_addr[i][7:4] < 4'ha ? flash_addr[i][7:4] + 8'h30 : + flash_addr[i][7:4] + 8'h57; + end +endgenerate + +logic [FLASH_MSG_SIZE-1:0][7:0] flash_msg; +//ascii-код строки: "finished write 0xflash_size bytes starting from 0xflash_addr\n" +assign flash_msg = {8'h66, 8'h69, 8'h6E, 8'h69, 8'h73, 8'h68, 8'h65, 8'h64, + 8'h20, 8'h77, 8'h72, 8'h69, 8'h74, 8'h65, 8'h20, 8'h30, + 8'h78, flash_size_ascii, 8'h20, 8'h62, 8'h79, + 8'h74, 8'h65, 8'h73, 8'h20, 8'h73, 8'h74, 8'h61, 8'h72, + 8'h74, 8'h69, 8'h6E, 8'h67, 8'h20, 8'h66, 8'h72, 8'h6F, + 8'h6D, 8'h20, 8'h30, 8'h78, flash_addr_ascii, + 8'h0a}; + +uart_rx rx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .rx_i (rx_i ), + .busy_o (rx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .rx_data_o (rx_data ), + .rx_valid_o (rx_valid ) +); + +uart_tx tx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .tx_o (tx_o ), + .busy_o (tx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .tx_data_i (tx_data ), + .tx_valid_i (tx_valid ) +); + +endmodule +``` + +Здесь уже объявлены: + +- `enum`-сигналы `state` и `next_state`; +- сигналы, `send_fin`, `size_fin`, `flash_fin`, `next_round`, используемые в качестве условий переходов между состояниями; +- счетчики `msg_counter`, `size_counter`, `flash_counter`, необходимые для реализации условий переходов; +- сигналы, необходимые для подключения модулей `uart_rx` и `uart_tx`: + - `rx_busy`, + - `rx_valid`, + - `tx_busy`, + - `tx_valid`, + - `rx_data`, + - `tx_data`; +- модули `uart_rx`, `uart_tx`; +- сигналы `init_msg`, `flash_msg`, хранящие ascii-код ответов программатора, а так же логику и сигналы, необходимые для реализации этих ответов: + - `flash_size`, + - `flash_addr`, + - `flash_size_ascii`, + - `flash_addr_ascii`. + +#### Реализация модуля + +Для реализации данного модуля, необходимо реализовать все объявленные выше сигналы, кроме сигналов: + +- `rx_busy`, `rx_valid`, `rx_data`, `tx_busy` (т.к. те уже подключены к выходам модулей `uart_rx`/`uart_tx`), +- `flash_size_ascii`, `flash_addr_ascii`, `init_msg`, `flash_msg` (т.е. они уже реализованы в представленной выше логике). + +Так же необходимо реализовать выходы модуля: + +- `instr_addr_o`; +- `instr_wdata_o`; +- `instr_write_enable_o`; +- `data_addr_o`; +- `data_wdata_o`; +- `data_write_enable_o`; +- `core_reset_o`. + +##### Реализация конечного автомата + +Для реализации сигналов `state`, `next_state` представлен граф переходов между состояниями. В случае, если не выполняется ни одно из условий перехода, автомат должен остаться в текущем состоянии. + +Логика условий переходов уже была представлена сразу после графа переходов. + +Для работы логики переходов, необходимо реализовать счетчики `size_counter`, `flash_counter`, `msg_counter`. + +`size_counter` должен сбрасываться в значение `4`, а так же принимать это значение во всех состояниях кроме: `RCV_SIZE`, `RCV_NEXT_COMMAND`. В данных двух состояниях счетчик должен декрементироваться в случае, если `rx_valid` равен единице. + +`flash_counter` должен сбрасываться в значение `flash_size`, а так же принимать это значение во всех состояниях кроме `FLASH`. В этом состоянии счетчик должен декрементироваться в случае, если `rx_valid` равен единице. + +`msg_counter` должен сбрасываться в значение `INIT_MSG_SIZE-1`. + +Счетчик должен инициализироваться следующим образом: + +- в состоянии `FLASH` счетчик должен принимать значение `FLASH_MSG_SIZE-1`, +- в состоянии `RCV_SIZE` счетчик должен принимать значение `ACK_MSG_SIZE-1`, +- в состоянии `RCV_NEXT_COMMAND` счетчик должен принимать значение `INIT_MSG_SIZE-1`. + +В состояниях: `INIT_MSG`, `SIZE_ACK`, `FLASH_ACK` счетчик должен декрементироваться в случае, если `tx_valid` равен единице. + +Во всех остальных ситуациях счетчик должен сохранять свое значение. + +##### Реализация сигналов uart_tx + +Сигнал `tx_valid` должен быть равен единице только когда `tx_busy` равен нулю, и конечный автомат находится в одном из следующих состояний: + +- `INIT_MSG`, +- `SIZE_ACK`, +- `FLASH_ACK` + +Иными словами, `tx_valid` равен единице когда автомат находится в состоянии, отвечающем за передачу сообщений от программатора и в данный момент программатор не отправляет очередной байт сообщения. + +Сигнал `tx_data` должен нести очередной байт одного из передаваемых сообщений: + +- в состоянии `INIT_MSG` передается очередной байт сообщения `init_msg` +- в состоянии `SIZE_ACK` передается очередной байт сообщения `flash_size` +- в состоянии `FLASH_ACK` передается очередной байт сообщения `flash_msg`. + +В остальных состояниях он равен нулю. Для отсчета байт используется счетчик `msg_counter`. + +##### Реализация оставшейся части логики + +Регистр `flash_size` работает следующим образом: + +- сбрасывается в 0; +- в состоянии `RCV_SIZE` при `rx_valid` равном единице становится равен `{flash_size[2:0], rx_data}` (сдвигается на 1 байт влево и на освободившееся место ставится очередной пришедший байт); +- в остальных ситуациях сохраняет свое значение. + +Регистр `flash_addr` почти полностью повторяет поведение `flash_size`: + +- сбрасывается в 0; +- в состоянии `RCV_NEXT_COMMAND` при `rx_valid` равном единице становится равен `{flash_size[2:0], rx_data}` (сдвигается на 1 байт влево и на освободившееся место ставится очередной пришедший байт); +- в остальных ситуациях сохраняет свое значение. + +Сигнал `core_reset_o` равен единице в случае, если состояние конечного автомата не `FINISH`. + +Оставшиеся сигналы (сигналы интерфейса памяти инструкций и памяти данных) работают по схожей логике. + +Сигналы памяти инструкций (`instr_addr_o`, `instr_wdata_o`, `instr_write_enable_o`): + +- сбрасываются в ноль +- в случае состояния `FLASH` и пришедшего сигнала `rx_valid`, если значение `flash_addr` меньше размера памяти инструкций в байтах: + - `instr_wdata_o` принимает значение `{instr_wdata_o[23:0], rx_data}` (справа вдвигается очередной пришедший байт) + - `instr_write_enable_o` становится равен `(flash_counter[1:0] == 2'b01)` + - `instr_addr_o` становится равен `flash_addr + flash_counter - 1` +- во всех остальных ситуациях `instr_wdata_o` и `instr_addr_o` сохраняют свое значение, а `instr_write_enable_o` сбрасывается в ноль. + +Сигналы памяти данных (`data_addr_o`, `data_wdata_o`, `data_write_enable_o`): + +- сбрасываются в ноль +- в случае состояния `FLASH` и пришедшего сигнала `rx_valid`, если значение `flash_addr` больше либо равно размеру памяти инструкций в байтах: + - `data_wdata_o` принимает значение `{data_wdata_o[23:0], rx_data}` (справа вдвигается очередной пришедший байт) + - `data_write_enable_o` становится равен `(flash_counter[1:0] == 2'b01)` + - `data_addr_o` становится равен `flash_addr + flash_counter - 1` +- во всех остальных ситуациях `data_wdata_o` и `data_addr_o` сохраняют свое значение, а `data_write_enable_o` сбрасывается в ноль. + +### Интеграция программатора в riscv_unit + +![../../.pic/Labs/lab_14_programming_device/fig_04.drawio.png](../../.pic/Labs/lab_14_programming_device/fig_04.drawio.png) + +В первую очередь, необходимо заменить память инструкций и добавить новый модуль. После чего подключить программатор к памяти инструкций и мультиплексировать выход интерфейса памяти данных программатора с интерфейсом памяти данных LSU. Сигнал сброса процессора необходимо заменить на выход `core_reset_o`. + +В случае, если использовалось периферийное устройство `uart_tx`, необходимо мультиплексировать его выход `tx_o` с одноименным выходом программатора аналогично тому, как это было сделано с сигналами интерфейса памяти данных. + +## Порядок выполнения задания + +1. Напишите модуль перезаписываемой памяти инструкций. Данный модуль будет аналогичен памяти данных, только в нем не будет сигнала `mem_req_i`. +2. Создайте модуль bluster, используя предоставленный код. + 1. Опишите конечный автомат используя сигналы `state`, `next_state`, `send_fin`, `size_fin`, `flash_fin`, `next_round`. + 2. [Реализуйте](#описание-модуля) логику сигналов `send_fin`, `size_fin`, `flash_fin`, `next_round`. + 3. [Реализуйте](#реализация-конечного-автомата) логику счетчиков `size_counter`, `flash_counter`, `msg_counter`. + 4. [Реализуйте](#реализация-сигналов-uart_tx) логику сигналов `tx_valid`, `tx_data`. + 5. [Реализуйте](#реализация-оставшейся-части-логики) логику оставшихся сигналов. +3. После описания модуля, его необходимо проверить с помощью тестового окружения. + 1. Тестовое окружение находится [здесь](tb_bluster.sv). + 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). + 3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_bluster`). + 4. Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста! +4. Интегрируйте программатор в модуль `riscv_unit`. + 1. Обновите память инструкций. + 2. Добавьте модуль программатор. + 3. Подключите программатор к процессорной системе. + 1. Интерфейс памяти инструкций подключается к порту записи обновленной памяти инструкций. + 2. Интерфейс памяти данных мультиплексируется с интерфейсом памяти данных модуля LSU + 3. Замените сигнал сброса модуля `riscv_core` сигналом `core_reset_o`. + 4. В случае если у вас есть периферийное устройство `uart_tx` его выход `tx_o` необходимо мультиплексировать с выходом `tx_o` программатора аналогично тому, как был мультиплексирован интерфейс памяти данных. +5. После интеграции модуля, его необходимо проверить с помощью тестового окружения. + 1. Тестовое окружение находится [здесь](tb_top_asic.sv). + 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). + 3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_top_asic`). + 4. Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста! +6. Переходить к следующему пункту можно только после того, как вы полностью убедились в работоспособности модуля на этапе моделирования (увидели что в память инструкций и данных были записаны корректные данные). Генерация битстрима будет занимать у вас долгое время, а итогом вы получите результат: заработало / не заработало, без какой-либо дополнительной информации, поэтому без прочного фундамента на моделировании далеко уехать у вас не выйдет. +7. Подключите к проекту файл ограничений ([nexys_a7_100t.xdc](nexys_a7_100t.xdc)), если тот еще не был подключен, либо замените его содержимое данными из файла к этой лабораторной работе. +8. Проверьте работу вашей процессорной системы на отладочном стенде с ПЛИС. + 1. Для прошивки процессорной системы используется скрипт [flash.py](flash.py). diff --git a/Labs/14. Programming device/flash.py b/Labs/14. Programming device/flash.py new file mode 100644 index 0000000..3f12b9c --- /dev/null +++ b/Labs/14. Programming device/flash.py @@ -0,0 +1,83 @@ +import argparse +import serial + +parser = argparse.ArgumentParser() +parser.add_argument("instr", type=str, help="File for instr mem initialization") +parser.add_argument("comport", type=str, help="COM-port name") +parser.add_argument("-d", "--data", type=str, help="File for data mem initialization") +parser.add_argument("-t", "--tiff", type=str, help="File for tiff mem initialization") + +args = parser.parse_args() + +def parse_file(fname: str, base: int = 16, word_size: int = 2) -> bytes: + res_bytes=b'' + with open(fname, 'r') as fp: + for line in fp: + if line[0] == '@': + continue + for word in line.split(): + res_bytes += bytes(int(word,base).to_bytes(len(word)//word_size,"little")) + return res_bytes[::-1] + +def flash(data: bytes, port: serial.Serial, mem_name: str): + assert(len(mem_name) == 4) + + if data: + data_len = len(data) + else: + data_len = 0 + data_len_bytes = data_len.to_bytes(4, "big") + port.write(data_len_bytes) + + data_len_ack = port.read(4) + print(int.from_bytes(data_len_ack,"big")) + assert(data_len_ack == data_len_bytes) + + if(data): + port.write(data) + + print("finished write {} mem".format(mem_name)) + + data_flash_ack = port.read(10) + data_flash_ack_str = data_flash_ack.decode("ascii") + print(data_flash_ack_str) + assert(data_flash_ack_str == "{} done\n".format(mem_name)) + + + +# Main block + +inst_file = args.instr +data_file = args.data +tiff_file = args.tiff +com = args.comport + +instr = parse_file(inst_file) + +if data_file: + data = parse_file(data_file) +else: + data = b'' + +if tiff_file: + tiff = parse_file(tiff_file, 2, 8) +else: + tiff = b'' + + +ser = serial.Serial( + port=com, + baudrate=115200, + parity=serial.PARITY_EVEN, + stopbits=serial.STOPBITS_ONE, + bytesize=serial.EIGHTBITS, + timeout=None +) + +init_msg = ser.read(6) +print(init_msg.decode("ascii")) +assert(init_msg == b'ready\n') + +flash(instr, ser, "inst") +flash(data, ser, "data") +flash(tiff, ser, "tiff") diff --git a/Labs/14. Programming device/tb_bluster.sv b/Labs/14. Programming device/tb_bluster.sv new file mode 100644 index 0000000..e9b6696 --- /dev/null +++ b/Labs/14. Programming device/tb_bluster.sv @@ -0,0 +1,540 @@ +module tb_blaster(); + + logic clk_i; + logic rst_i; + logic rx_i; + logic tx_o; + logic [ 31:0] instr_addr_o; + logic [ 31:0] instr_wdata_o; + logic instr_write_enable_o; + logic [ 31:0] data_addr_o; + logic [ 31:0] data_wdata_o; + logic data_write_enable_o; + logic [ 31:0] tiff_addr_o; + logic [127:0] tiff_wdata_o; + logic tiff_write_enable_o; + logic core_reset_o; + + logic rx_busy, rx_valid, tx_busy, tx_valid; + logic [7:0] rx_data, tx_data; + + logic [31:0] instr_addr_i; + logic [31:0] instr_rdata_o; + logic [31:0] tiff_addr_i; + logic [127:0] tiff_rdata_o; + + logic [3:0] [7:0] flash_addr; + logic [3:0] [7:0] instr_size; + logic [3:0] [7:0] instr_size_ack; + logic [3:0] [7:0] data_size; + logic [3:0] [7:0] data_size_ack; + logic [3:0] [7:0] tiff_size; + logic [3:0] [7:0] tiff_size_ack; + + logic [7:0] instr_mem_byte[$]; + logic [7:0] data_mem_byte[$]; + logic [7:0] tiff_mem_byte [$]; + + localparam INIT_MSG_SIZE = 40; + localparam MSG_DONE_SIZE = 57; + localparam MSG_ACK_SIZE = 4; + + byte init_str[INIT_MSG_SIZE]; + byte done_str[MSG_DONE_SIZE]; + + always #50ns clk_i = !clk_i; + + initial begin + $timeformat(-9, 2, " ns", 3); + clk_i = 0; + rst_i <= 0; + @(posedge clk_i); + rst_i <= 1; + repeat(2) @(posedge clk_i); + rst_i <= 0; + instr_size = instr_mem_byte.size(); + data_size = data_mem_byte.size(); + tiff_size = tiff_mem_byte.size(); + +/* + INIT_MSG +*/ + for(int i = 0; i < INIT_MSG_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + init_str[i] = rx_data; + end + $display("%s", init_str); + wait(tx_o); +// ---------------------------------------------- + + repeat(10000)@(posedge clk_i); + +/* + RCV_INSTR_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = instr_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + INSTR_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + instr_size_ack[i] = rx_data; + @(posedge clk_i); + end + $display("%h", instr_size); + assert(instr_size_ack == instr_size) + else $error("ack: %0h, size: %0h", instr_size_ack, instr_size); + wait(tx_o); +// ---------------------------------------------- + + + +/* + INSTR_FLASH +*/ + if(instr_size)repeat(10000)@(posedge clk_i); + for(int i = instr_size-1; i >=0; i--) begin + tx_data = instr_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + INSTR_FLASH_ACK +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(tx_o); +// ---------------------------------------------- + + + + repeat(10000)@(posedge clk_i); + +/* + RCV_NEXT_COMMAND +*/ flash_addr = 32'h4000; + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = flash_addr[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end + + +/* + INIT_MSG +*/ + for(int i = 0; i < INIT_MSG_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + init_str[i] = rx_data; + end + $display("%s", init_str); + wait(tx_o); +// ---------------------------------------------- + +/* + RCV_DATA_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = data_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + DATA_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + data_size_ack[i] = rx_data; + @(posedge clk_i); + end + $display("%h", data_size); + assert(data_size_ack == data_size) + else $error("ack: %0h, size: %0h", data_size_ack, data_size); + wait(tx_o); +// ---------------------------------------------- + + +/* + DATA_FLASH +*/ + if(data_size)repeat(10000)@(posedge clk_i); + for(int i = data_size-1; i >=0; i--) begin + tx_data = data_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + DATA_FLASH_ACK +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(tx_o); +// ---------------------------------------------- + repeat(10000)@(posedge clk_i); + + +/* + RCV_NEXT_COMMAND +*/ flash_addr = 32'h0800_0000; + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = flash_addr[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end + +/* + INIT_MSG +*/ + for(int i = 0; i < INIT_MSG_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + init_str[i] = rx_data; + end + $display("%s", init_str); + wait(tx_o); +// ---------------------------------------------- + +/* + RCV_TIFF_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = tiff_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + TIFF_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + tiff_size_ack[i] = rx_data; + @(posedge clk_i); + end + $display("%h", tiff_size); + assert(tiff_size_ack == tiff_size) + else $display("ack: %0h, size: %0h", tiff_size_ack, tiff_size); + wait(tx_o); +// ---------------------------------------------- + + + +/* + TIFF_FLASH +*/ + if(tiff_size)repeat(10000)@(posedge clk_i); + for(int i = tiff_size-1; i >=0; i--) begin + tx_data = tiff_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + TIFF_FLASH_ACK, FINISH +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(!rx_busy) + @(posedge clk_i) + +/* + RCV_NEXT_COMMAND +*/ flash_addr = 32'h0000_0000; + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = flash_addr[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end + + assert(!pc_reset_o) + else $error("reset is not equal zero at the end"); +// ---------------------------------------------- + + repeat(10000)@(posedge clk_i); + + $finish(); + end + + + bluster blust(.*); + + uart_rx rx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .rx_i (tx_o ), + .busy_o (rx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .rx_data_o (rx_data ), + .rx_valid_o (rx_valid ) +); + +uart_tx tx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .tx_o (rx_i ), + .busy_o (tx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .tx_data_i (tx_data ), + .tx_valid_i (tx_valid ) +); + + rw_instr_mem imem( + .clk_i (clk_i ) , + .addr_i (instr_addr_i ) , + .read_data_o (instr_rdata_o ) , + .write_addr_i (instr_addr_o ) , + .write_data_i (instr_wdata_o ) , + .write_enable_i(instr_write_enable_o) + ); + + ext_mem dmem( + .clk_i (clk_i ), + .mem_req_i (data_addr_o[31:24] == 0), + .write_enable_i (data_write_enable_o), + .byte_enable_i (4'b1111 ), + .addr_i (data_addr_o ), + .write_data_i (data_wdata_o ), + .read_data_o (), + .ready_o () + ); + + ext_mem tmem( + .clk_i (clk_i ), + .mem_req_i (data_addr_o[31:24] == 8), + .write_enable_i (data_write_enable_o), + .byte_enable_i (4'b1111 ), + .addr_i (data_addr_o ), + .write_data_i (data_wdata_o ), + .read_data_o (), + .ready_o () + ); + +initial instr_mem_byte = { +8'h93, 8'h00, 8'h10, 8'h00, 8'h37, 8'h01, 8'h00, 8'h06, 8'hB7, 8'hC1, 8'h01, 8'h00, 8'h93, 8'h81, 8'h01, 8'h20, +8'h23, 8'h26, 8'h31, 8'h00, 8'h13, 8'h02, 8'h10, 8'h00, 8'h23, 8'h28, 8'h41, 8'h00, 8'h93, 8'h02, 8'h10, 8'h00, +8'h93, 8'h80, 8'h10, 8'h00, 8'h83, 8'h23, 8'h81, 8'h00, 8'h63, 8'h14, 8'h70, 8'h00, 8'h6F, 8'h00, 8'h00, 8'h00, +8'h6F, 8'h00, 8'h00, 8'h00, 8'h23, 8'h20, 8'h11, 8'h00, 8'h6F, 8'h00, 8'h00, 8'h00 +}; + +initial #1 data_mem_byte = instr_mem_byte; + +initial tiff_mem_byte = { +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000101, 8'b00000101, 8'b00000101, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010010, 8'b00010010, 8'b00111111, 8'b00010010, 8'b00010010, 8'b00010010, 8'b00111111, 8'b00010010, 8'b00010010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000100, 8'b00001110, 8'b00010001, 8'b00010001, 8'b00000001, 8'b00001110, 8'b00010000, 8'b00010000, 8'b00010001, 8'b00010001, 8'b00001110, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000010, 8'b00000101, 8'b01000101, 8'b00100010, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00100010, 8'b01010001, 8'b01010000, 8'b00100000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001100, 8'b00010010, 8'b00010010, 8'b00010010, 8'b01001100, 8'b01001010, 8'b00110001, 8'b00100001, 8'b00110001, 8'b01001110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00010010, 8'b00001100, 8'b00111111, 8'b00001100, 8'b00010010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00011111, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00001111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00010000, 8'b00010000, 8'b00001000, 8'b00001000, 8'b00000100, 8'b00000100, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00110001, 8'b00101001, 8'b00101001, 8'b00100101, 8'b00100101, 8'b00100011, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001000, 8'b00001100, 8'b00001010, 8'b00001001, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100000, 8'b00100000, 8'b00011100, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00010000, 8'b00011000, 8'b00010100, 8'b00010010, 8'b00010001, 8'b00111111, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00001000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00001000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00111100, 8'b01000010, 8'b10011001, 8'b10100001, 8'b10111001, 8'b10100101, 8'b01111001, 8'b00000010, 8'b01111100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00001111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00001111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001001, 8'b00000111, 8'b00001001, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01100011, 8'b01010101, 8'b01001001, 8'b01001001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100011, 8'b00100101, 8'b00101001, 8'b00110001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00101001, 8'b00110001, 8'b00111110, 8'b00100000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000010, 8'b00001100, 8'b00010000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01111111, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00010100, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01010101, 8'b01100011, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00010010, 8'b00001100, 8'b00001100, 8'b00010010, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00100000, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000111, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000010, 8'b00000100, 8'b00000100, 8'b00001000, 8'b00001000, 8'b00010000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000111, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000111, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000100, 8'b00001010, 8'b00010001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011100, 8'b00100010, 8'b00000010, 8'b00000010, 8'b00001111, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00110001, 8'b00101110, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010000, 8'b00000000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010001, 8'b00010001, 8'b00001110, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00110111, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011101, 8'b00000011, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00011110, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00011111, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00010100, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01010101, 8'b00100010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b00100010, 8'b00010100, 8'b00001000, 8'b00010100, 8'b00100010, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00110001, 8'b00101110, 8'b00100000, 8'b00010000, 8'b00001111, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000011, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000011, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000011, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100110, 8'b00011001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000011, 8'b00000101, 8'b00000101, 8'b00000011, 8'b00000000, 8'b00001100, 8'b00001100, 8'b00000100, 8'b00101100, 8'b00100000, 8'b00100000, 8'b01100000, 8'b00000000, 8'b00000000, 8'b00000000 +}; + +endmodule + + +module rw_tiff_mem( + input logic clk_i, + input logic [ 31:0] addr_i, + output logic [127:0] read_data_o, + + input logic [ 31:0] write_addr_i, + input logic [127:0] write_data_i, + input logic write_enable_i +); + +logic [127:0] rom [256]; + +assign read_data_o = rom[addr_i]; + +always_ff @(posedge clk_i) begin + if(write_enable_i) begin + rom[write_addr_i] <= write_data_i; + end +end + +endmodule \ No newline at end of file diff --git a/Labs/14. Programming device/tb_top_asic.sv b/Labs/14. Programming device/tb_top_asic.sv new file mode 100644 index 0000000..dd15168 --- /dev/null +++ b/Labs/14. Programming device/tb_top_asic.sv @@ -0,0 +1,453 @@ +module tb_top_asic(); + + logic clk10mhz_i; + logic aresetn_i; + logic rx_i; + logic tx_o; + logic clk_i; + logic rst_i; + + assign aresetn_i = !rst_i; + assign clk10mhz_i = clk_i; + + logic rx_busy, rx_valid, tx_busy, tx_valid; + logic [7:0] rx_data, tx_data; + + logic [3:0] [7:0] instr_size_ack; + logic [3:0] [7:0] data_size_ack; + logic [3:0] [7:0] tiff_size = 32'd0; + logic [3:0] [7:0] tiff_size_ack; + byte init_str[6]; + byte done_str[10]; + logic [7:0] instr_mem_byte[]; + logic [7:0] data_mem_byte[]; + logic [3:0] [7:0] instr_size; + logic [3:0] [7:0] data_size; + + initial begin + // $readmemh("tb_coremark_instr.mem", instr_mem_byte); + // $readmemh("tb_coremark_data.mem", data_mem_byte); + // instr_size = instr_mem_byte.size(); + // data_size = data_mem_byte.size(); + instr_size = 0; + data_size = 0; + end + + logic [7:0] tiff_mem_byte [2048]; + + localparam INIT_MSG_SIZE = 6; + localparam MSG_DONE_SIZE = 10; + localparam MSG_ACK_SIZE = 4; + + always #50ns clk_i = !clk_i; + + byte coremark_msg[103]; + integer coremark_cntr; + + initial begin + $timeformat(-9, 2, " ns", 3); + clk_i = 0; + rst_i <= 0; + @(posedge clk_i); + rst_i <= 1; + repeat(2) @(posedge clk_i); + rst_i <= 0; + +/* + INIT_MSG +*/ + for(int i = 0; i < INIT_MSG_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + init_str[i] = rx_data; + end + $display("%s", init_str); + wait(tx_o); +// ---------------------------------------------- + + repeat(10000)@(posedge clk_i); + +/* + IDLE, RCV_INSTR_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = instr_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + INSTR_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + instr_size_ack[i] = rx_data; + @(posedge clk_i); + end + assert(instr_size_ack == instr_size) + else $error("ack: %0h, size: %0h", instr_size_ack, instr_size); + wait(tx_o); +// ---------------------------------------------- + + + +/* + INSTR_FLASH +*/ + if(instr_size)repeat(10000)@(posedge clk_i); + for(int i = instr_size-1; i >=0; i--) begin + tx_data = instr_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + INSTR_FLASH_ACK +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(tx_o); +// ---------------------------------------------- + + + + repeat(10000)@(posedge clk_i); + + + +/* + RCV_DATA_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = data_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + DATA_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + data_size_ack[i] = rx_data; + @(posedge clk_i); + end + assert(data_size_ack == data_size) + else $error("ack: %0h, size: %0h", data_size_ack, data_size); + wait(tx_o); +// ---------------------------------------------- + + +/* + DATA_FLASH +*/ + if(data_size)repeat(10000)@(posedge clk_i); + for(int i = data_size-1; i >=0; i--) begin + tx_data = data_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + DATA_FLASH_ACK +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(tx_o); +// ---------------------------------------------- + repeat(10000)@(posedge clk_i); + + + + + +/* + RCV_TIFF_SIZE +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + tx_data = tiff_size[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + TIFF_SIZE_ACK +*/ + for(int i = MSG_ACK_SIZE-1; i >= 0; i--) begin + while(!rx_valid) @(posedge clk_i); + tiff_size_ack[i] = rx_data; + @(posedge clk_i); + end + assert(tiff_size_ack == tiff_size) + else $display("ack: %0h, size: %0h", tiff_size_ack, tiff_size); + wait(tx_o); +// ---------------------------------------------- + + + +/* + TIFF_FLASH +*/ + if(tiff_size)repeat(10000)@(posedge clk_i); + for(int i = tiff_size-1; i >=0; i--) begin + tx_data = tiff_mem_byte[i]; + tx_valid = 1'b1; + @(posedge clk_i); + tx_valid = 1'b0; + @(posedge clk_i); + while(tx_busy) @(posedge clk_i); + end +// ---------------------------------------------- + + +/* + TIFF_FLASH_ACK, FINISH +*/ + for(int i = 0; i < MSG_DONE_SIZE; i++) begin + @(posedge clk_i); + while(!rx_valid)@(posedge clk_i); + done_str[i] = rx_data; + end + $display("%t %s", $time, done_str); + wait(!rx_busy) + @(posedge clk_i) + // assert(!pc_stall_o) + // else $error("stall is not equal zero at the end"); +// ---------------------------------------------- + + repeat(10000)@(posedge clk_i); + coremark_cntr = 0; + coremark_msg = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}; + forever begin + @(posedge clk_i); + if(rx_valid) begin + if((rx_data == 10) | (rx_data == 13)) begin + $display("%s", coremark_msg); + coremark_cntr = 0; + coremark_msg = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}; + end + else begin + coremark_msg[coremark_cntr] = rx_data; + coremark_cntr++; + end + end + end + // $finish(); + end + + + riscv_top_asic DUT(.clk10mhz_i, .aresetn_i, .rx_i, .tx_o); + + uart_rx rx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .rx_i (tx_o ), + .busy_o (rx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .rx_data_o (rx_data ), + .rx_valid_o (rx_valid ) +); + +uart_tx tx( + .clk_i (clk_i ), + .rst_i (rst_i ), + .tx_o (rx_i ), + .busy_o (tx_busy ), + .baudrate_i (17'd115200 ), + .parity_en_i(1'b1 ), + .stopbit_i (1'b1 ), + .tx_data_i (tx_data ), + .tx_valid_i (tx_valid ) +); + + +initial tiff_mem_byte = { +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00011110, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000101, 8'b00000101, 8'b00000101, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010010, 8'b00010010, 8'b00111111, 8'b00010010, 8'b00010010, 8'b00010010, 8'b00111111, 8'b00010010, 8'b00010010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000100, 8'b00001110, 8'b00010001, 8'b00010001, 8'b00000001, 8'b00001110, 8'b00010000, 8'b00010000, 8'b00010001, 8'b00010001, 8'b00001110, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000010, 8'b00000101, 8'b01000101, 8'b00100010, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00100010, 8'b01010001, 8'b01010000, 8'b00100000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001100, 8'b00010010, 8'b00010010, 8'b00010010, 8'b01001100, 8'b01001010, 8'b00110001, 8'b00100001, 8'b00110001, 8'b01001110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00010010, 8'b00001100, 8'b00111111, 8'b00001100, 8'b00010010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00011111, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00001111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00010000, 8'b00010000, 8'b00001000, 8'b00001000, 8'b00000100, 8'b00000100, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00110001, 8'b00101001, 8'b00101001, 8'b00100101, 8'b00100101, 8'b00100011, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001000, 8'b00001100, 8'b00001010, 8'b00001001, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100000, 8'b00100000, 8'b00011100, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00010000, 8'b00011000, 8'b00010100, 8'b00010010, 8'b00010001, 8'b00111111, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000010, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00001000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000010, 8'b00000100, 8'b00001000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00111100, 8'b01000010, 8'b10011001, 8'b10100001, 8'b10111001, 8'b10100101, 8'b01111001, 8'b00000010, 8'b01111100, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00001111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00001111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00001111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001001, 8'b00000111, 8'b00001001, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01100011, 8'b01010101, 8'b01001001, 8'b01001001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100011, 8'b00100101, 8'b00101001, 8'b00110001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00101001, 8'b00110001, 8'b00111110, 8'b00100000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000010, 8'b00001100, 8'b00010000, 8'b00100000, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01111111, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00010100, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01000001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01010101, 8'b01100011, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00010010, 8'b00001100, 8'b00001100, 8'b00010010, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00111111, 8'b00100000, 8'b00100000, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000111, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000010, 8'b00000100, 8'b00000100, 8'b00001000, 8'b00001000, 8'b00010000, 8'b00010000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000111, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000111, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000100, 8'b00001010, 8'b00010001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00111111, 8'b00000001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011100, 8'b00100010, 8'b00000010, 8'b00000010, 8'b00001111, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00110001, 8'b00101110, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00010000, 8'b00000000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010000, 8'b00010001, 8'b00010001, 8'b00001110, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00100001, 8'b00100001, 8'b00010001, 8'b00001111, 8'b00010001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00110111, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011111, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00011111, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111110, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00100000, 8'b00100000, 8'b00100000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011101, 8'b00000011, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00011110, 8'b00100001, 8'b00000001, 8'b00011110, 8'b00100000, 8'b00100001, 8'b00011110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000100, 8'b00000100, 8'b00011111, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00111110, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b00100010, 8'b00100010, 8'b00010100, 8'b00010100, 8'b00001000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b01000001, 8'b01001001, 8'b01001001, 8'b01001001, 8'b01010101, 8'b00100010, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b01000001, 8'b00100010, 8'b00010100, 8'b00001000, 8'b00010100, 8'b00100010, 8'b01000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00100001, 8'b00110001, 8'b00101110, 8'b00100000, 8'b00010000, 8'b00001111, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00111111, 8'b00010000, 8'b00001000, 8'b00000100, 8'b00000010, 8'b00000001, 8'b00111111, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00011000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000011, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00000011, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00011000, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000100, 8'b00000011, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000000, 8'b00100110, 8'b00011001, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, 8'b00000000, +8'b00000000, 8'b00000011, 8'b00000101, 8'b00000101, 8'b00000011, 8'b00000000, 8'b00001100, 8'b00001100, 8'b00000100, 8'b00101100, 8'b00100000, 8'b00100000, 8'b01100000, 8'b00000000, 8'b00000000, 8'b00000000 +}; + +endmodule + + +module rw_tiff_mem( + input logic clk_i, + input logic [ 31:0] addr_i, + output logic [127:0] read_data_o, + + input logic [ 31:0] write_addr_i, + input logic [127:0] write_data_i, + input logic write_enable_i +); + +logic [127:0] rom [256]; + +assign read_data_o = rom[addr_i]; + +always_ff @(posedge clk_i) begin + if(write_enable_i) begin + rom[write_addr_i] <= write_data_i; + end +end + +endmodule \ No newline at end of file diff --git a/Labs/15. Coremark/README.md b/Labs/15. Coremark/README.md new file mode 100644 index 0000000..2d2be7f --- /dev/null +++ b/Labs/15. Coremark/README.md @@ -0,0 +1,2 @@ +# Лабораторная работа 15 "Оценка производительности" + diff --git a/Labs/README.md b/Labs/README.md index c69f08c..f079bb9 100644 --- a/Labs/README.md +++ b/Labs/README.md @@ -23,6 +23,7 @@ - [11. Интеграция подсистемы прерывания](#11-интеграция-подсистемы-прерывания) - [12. Периферийные устройства (PU)](#12-периферийные-устройства-pu) - [13. Программирование на языке высокого уровня](#13-программирование-на-языке-высокого-уровня) + - [14. Программатор](#14-программатор) ## Полезное @@ -168,3 +169,11 @@ ![../.pic/Labs/l10.png](../.pic/Labs/l10.png) В рамках данной лабораторной настраивается компилятор GCC для RISC-V и для разработанной системы пишется программное обеспечение на языке программирования C++. + +## 14. Программатор + +До этого момента, исполняемая процессором программа попадала в память инструкций через магический вызов `$readmemh`. Однако реальные микроконтроллеры не обладают такими возможностями. Программа из внешнего мира попадает в них посредством так называемого **программатора** — устройства, обеспечивающего запись программы в память микроконтроллера. Программатор записывает данные в постоянное запоминающее устройство (ПЗУ). Для того, чтобы программа попала из ПЗУ в память инструкций, после запуска контроллера сперва начинает исполняться **загрузчик** (**bootloader**) — небольшая программа, вшитая в память микроконтроллера на этапе изготовления, которая отвечает за первичную инициализацию и подготовку микроконтроллера к выполнению основной программы (включая её перенос из ПЗУ в память инструкций). + +В рамках данной лабораторной работы мы немного упростим процесс передачи программы: вместо записи в ПЗУ, программатор будет записывать её сразу в память инструкций, минуя загрузчик. + +![../.pic/Labs/lab_14_programming_device/fig_04.drawio.png](../.pic/Labs/lab_14_programming_device/fig_04.drawio.png)