From 940920d18b2892d42b50a8a8f4465082a971e49f Mon Sep 17 00:00:00 2001 From: pavel Date: Mon, 1 Jun 2026 06:19:27 +0300 Subject: [PATCH] added files --- .gitignore | 6 ++ Logic2_D7.csv | 101 +++++++++++++++++++ Logic2_to_FPGA.qpf | 30 ++++++ Logic2_to_FPGA.qsf | 71 +++++++++++++ omdazz.sdc | 3 + pattern_player.v | 82 +++++++++++++++ pattern_rom.v | 69 +++++++++++++ to_FPGA.py | 244 +++++++++++++++++++++++++++++++++++++++++++++ top.v | 53 ++++++++++ 9 files changed, 659 insertions(+) create mode 100644 Logic2_D7.csv create mode 100644 Logic2_to_FPGA.qpf create mode 100644 Logic2_to_FPGA.qsf create mode 100644 omdazz.sdc create mode 100644 pattern_player.v create mode 100644 pattern_rom.v create mode 100644 to_FPGA.py create mode 100644 top.v diff --git a/.gitignore b/.gitignore index 0a945a5..6726f50 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,12 @@ *.html */*/bd/*/ip/*/*.tcl */*/*/bd/*/ip/*/*.tcl +db/ +incremental_db/ +output_files/ +*.sof +*.pof +*.qws hw_handoff ipshared diff --git a/Logic2_D7.csv b/Logic2_D7.csv new file mode 100644 index 0000000..10eaf13 --- /dev/null +++ b/Logic2_D7.csv @@ -0,0 +1,101 @@ +Time [s],D7 +0.0000000000000000,0 +0.0000000010000000,0 +0.0000000020000000,1 +0.0000000030000000,1 +0.0000000040000000,0 +0.0000000050000000,0 +0.0000000060000000,1 +0.0000000070000000,1 +0.0000000080000000,0 +0.0000000090000000,0 +0.0000000100000000,1 +0.0000000110000000,1 +0.0000000120000000,0 +0.0000000130000000,0 +0.0000000140000000,1 +0.0000000150000000,1 +0.0000000160000000,0 +0.0000000170000000,0 +0.0000000180000000,1 +0.0000000190000000,1 +0.0000000200000000,0 +0.0000000210000000,0 +0.0000000220000000,1 +0.0000000230000000,1 +0.0000000240000000,0 +0.0000000250000000,0 +0.0000000260000000,1 +0.0000000270000000,1 +0.0000000280000000,0 +0.0000000290000000,0 +0.0000000300000000,1 +0.0000000310000000,1 +0.0000000320000000,0 +0.0000000330000000,0 +0.0000000340000000,1 +0.0000000350000000,1 +0.0000000360000000,0 +0.0000000370000000,0 +0.0000000380000000,1 +0.0000000390000000,1 +0.0000000400000000,0 +0.0000000410000000,0 +0.0000000420000000,1 +0.0000000430000000,1 +0.0000000440000000,0 +0.0000000450000000,0 +0.0000000460000000,1 +0.0000000470000000,1 +0.0000000480000000,0 +0.0000000490000000,0 +0.0000000500000000,1 +0.0000000510000000,1 +0.0000000520000000,0 +0.0000000530000000,0 +0.0000000540000000,1 +0.0000000550000000,1 +0.0000000560000000,0 +0.0000000570000000,0 +0.0000000580000000,1 +0.0000000590000000,1 +0.0000000600000000,0 +0.0000000610000000,0 +0.0000000620000000,1 +0.0000000630000000,1 +0.0000000640000000,0 +0.0000000650000000,0 +0.0000000660000000,1 +0.0000000670000000,1 +0.0000000680000000,0 +0.0000000690000000,0 +0.0000000700000000,1 +0.0000000710000000,1 +0.0000000720000000,0 +0.0000000730000000,0 +0.0000000740000000,1 +0.0000000750000000,1 +0.0000000760000000,0 +0.0000000770000000,0 +0.0000000780000000,1 +0.0000000790000000,1 +0.0000000800000000,0 +0.0000000810000000,0 +0.0000000820000000,1 +0.0000000830000000,1 +0.0000000840000000,0 +0.0000000850000000,0 +0.0000000860000000,1 +0.0000000870000000,1 +0.0000000880000000,0 +0.0000000890000000,0 +0.0000000900000000,1 +0.0000000910000000,1 +0.0000000920000000,0 +0.0000000930000000,0 +0.0000000940000000,1 +0.0000000950000000,1 +0.0000000960000000,0 +0.0000000970000000,0 +0.0000000980000000,1 +0.0000000990000000,1 \ No newline at end of file diff --git a/Logic2_to_FPGA.qpf b/Logic2_to_FPGA.qpf new file mode 100644 index 0000000..86d89c9 --- /dev/null +++ b/Logic2_to_FPGA.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 05:32:19 June 01, 2026 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "05:32:19 June 01, 2026" + +# Revisions + +PROJECT_REVISION = "Logic2_to_FPGA" diff --git a/Logic2_to_FPGA.qsf b/Logic2_to_FPGA.qsf new file mode 100644 index 0000000..c2ea0d7 --- /dev/null +++ b/Logic2_to_FPGA.qsf @@ -0,0 +1,71 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 05:32:19 June 01, 2026 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Logic2_to_FPGA_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE6E22C8 +set_global_assignment -name TOP_LEVEL_ENTITY top +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "05:32:19 JUNE 01, 2026" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V +set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)" +set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V" +set_location_assignment PIN_23 -to CLK50 +set_location_assignment PIN_87 -to GPIO0 +set_location_assignment PIN_7 -to KEY0 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLK50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO0 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY0 +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top +set_global_assignment -name SOURCE_FILE Logic2_to_FPGA.qpf +set_global_assignment -name SOURCE_FILE Logic2_to_FPGA.qsf +set_global_assignment -name SDC_FILE omdazz.sdc +set_global_assignment -name VERILOG_FILE top.v +set_global_assignment -name VERILOG_FILE pattern_rom.v +set_global_assignment -name VERILOG_FILE pattern_player.v \ No newline at end of file diff --git a/omdazz.sdc b/omdazz.sdc new file mode 100644 index 0000000..29cb6da --- /dev/null +++ b/omdazz.sdc @@ -0,0 +1,3 @@ +create_clock -period 20 -name clk [get_ports clk] + + diff --git a/pattern_player.v b/pattern_player.v new file mode 100644 index 0000000..5430ac7 --- /dev/null +++ b/pattern_player.v @@ -0,0 +1,82 @@ +// pattern_player.v +// Проигрывает один раз последовательность сегментов из pattern_rom. + +module pattern_player #( + parameter TICKS_WIDTH = 32, + parameter DEPTH = 128 +)( + input wire clk, + input wire rst, + input wire start, // 1 → начать воспроизведение + output reg out, // выход на пин + output reg busy // 1, пока идёт воспроизведение +); + + // Адрес в ROM + reg [$clog2(DEPTH)-1:0] addr; + + // Текущие {level, ticks} + reg [TICKS_WIDTH:0] cur_data; + reg [TICKS_WIDTH-1:0] ticks_cnt; + + wire [TICKS_WIDTH:0] rom_data; + + // Экземпляр ROM (Автогенерированный pattern_rom.v от Python-скрипта) + pattern_rom #( + .TICKS_WIDTH(TICKS_WIDTH), + .DEPTH(DEPTH) + ) rom_inst ( + .addr(addr), + .data(rom_data) + ); + + // Простая машина состояний + localparam IDLE = 2'd0; + localparam LOAD = 2'd1; + localparam RUN = 2'd2; + + reg [1:0] state; + + always @(posedge clk or posedge rst) begin + if (rst) begin + state <= IDLE; + addr <= 0; + ticks_cnt <= 0; + out <= 0; + busy <= 0; + end else begin + case (state) + IDLE: begin + busy <= 0; + if (start) begin + addr <= 0; + state <= LOAD; + busy <= 1; + end + end + + LOAD: begin + cur_data <= rom_data; + out <= rom_data[TICKS_WIDTH]; // уровень + ticks_cnt <= rom_data[TICKS_WIDTH-1:0]; // длительность + state <= RUN; + end + + RUN: begin + if (ticks_cnt == 0) begin + if (addr == DEPTH - 1) begin + // Проиграли все сегменты один раз → назад в IDLE + state <= IDLE; + end else begin + addr <= addr + 1; + state <= LOAD; + end + end else begin + ticks_cnt <= ticks_cnt - 1; + end + end + endcase + end + end + +endmodule \ No newline at end of file diff --git a/pattern_rom.v b/pattern_rom.v new file mode 100644 index 0000000..2d85770 --- /dev/null +++ b/pattern_rom.v @@ -0,0 +1,69 @@ +// Автогенерация из CSV: Logic2_D7.csv +// F_CLK_HZ = 48000000 +// Количество сегментов (DEPTH) = 50 + +module pattern_rom #( + parameter TICKS_WIDTH = 32, + parameter DEPTH = 50 +) ( + input wire [$clog2(DEPTH)-1:0] addr, + output reg [TICKS_WIDTH:0] data // {level[MSB], ticks[LSB:0]} +); + + // Простейший ROM на case по адресу + always @* begin + case (addr) + 0: data = {1'b0, 32'd1}; + 1: data = {1'b1, 32'd1}; + 2: data = {1'b0, 32'd1}; + 3: data = {1'b1, 32'd1}; + 4: data = {1'b0, 32'd1}; + 5: data = {1'b1, 32'd1}; + 6: data = {1'b0, 32'd1}; + 7: data = {1'b1, 32'd1}; + 8: data = {1'b0, 32'd1}; + 9: data = {1'b1, 32'd1}; + 10: data = {1'b0, 32'd1}; + 11: data = {1'b1, 32'd1}; + 12: data = {1'b0, 32'd1}; + 13: data = {1'b1, 32'd1}; + 14: data = {1'b0, 32'd1}; + 15: data = {1'b1, 32'd1}; + 16: data = {1'b0, 32'd1}; + 17: data = {1'b1, 32'd1}; + 18: data = {1'b0, 32'd1}; + 19: data = {1'b1, 32'd1}; + 20: data = {1'b0, 32'd1}; + 21: data = {1'b1, 32'd1}; + 22: data = {1'b0, 32'd1}; + 23: data = {1'b1, 32'd1}; + 24: data = {1'b0, 32'd1}; + 25: data = {1'b1, 32'd1}; + 26: data = {1'b0, 32'd1}; + 27: data = {1'b1, 32'd1}; + 28: data = {1'b0, 32'd1}; + 29: data = {1'b1, 32'd1}; + 30: data = {1'b0, 32'd1}; + 31: data = {1'b1, 32'd1}; + 32: data = {1'b0, 32'd1}; + 33: data = {1'b1, 32'd1}; + 34: data = {1'b0, 32'd1}; + 35: data = {1'b1, 32'd1}; + 36: data = {1'b0, 32'd1}; + 37: data = {1'b1, 32'd1}; + 38: data = {1'b0, 32'd1}; + 39: data = {1'b1, 32'd1}; + 40: data = {1'b0, 32'd1}; + 41: data = {1'b1, 32'd1}; + 42: data = {1'b0, 32'd1}; + 43: data = {1'b1, 32'd1}; + 44: data = {1'b0, 32'd1}; + 45: data = {1'b1, 32'd1}; + 46: data = {1'b0, 32'd1}; + 47: data = {1'b1, 32'd1}; + 48: data = {1'b0, 32'd1}; + 49: data = {1'b1, 32'd1}; + default: data = {1'b0, {TICKS_WIDTH{1'b0}}}; + endcase + end +endmodule diff --git a/to_FPGA.py b/to_FPGA.py new file mode 100644 index 0000000..c33f085 --- /dev/null +++ b/to_FPGA.py @@ -0,0 +1,244 @@ +import csv +from pathlib import Path + +# ========================== +# НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ +# ========================== + +# Входной файл из Logic 2 (CSV только с Time [s] и D7) +CSV_FILE = "Logic2_D7.csv" + +# Выходной Verilog-файл +VERILOG_FILE = "pattern_rom.v" + +# Тактовая частота в МК/FPGA, Гц (должна совпадать с тем, что реально в железе) +F_CLK_HZ = 48_000_000 # пример: 48 МГц + +# Имена колонок в CSV (посмотри заголовок в своём файле и подгони при необходимости) +TIME_COL = "Time [s]" # колонка с временем +LEVEL_COL = "D7" # колонка с уровнем сигнала + +# Сколько бит отвести под счётчик тиков в Verilog +TICKS_WIDTH = 32 + + +# ========================== +# ЧТЕНИЕ CSV ИЗ LOGIC 2 +# ========================== + +def read_digital_trace(csv_path: str): + """ + Читает CSV-файл в формате Logic 2 и возвращает два списка: + times[i] - время в секундах (float), + levels[i] - уровень (0 или 1) в моменты времени times[i]. + + Ожидается, что первая строка CSV — заголовок с колонками TIME_COL и LEVEL_COL. + """ + times = [] + levels = [] + + with open(csv_path, newline="") as f: + reader = csv.DictReader(f) + + # Проверяем наличие нужных столбцов + if TIME_COL not in reader.fieldnames or LEVEL_COL not in reader.fieldnames: + raise RuntimeError( + f"В CSV нет ожидаемых колонок '{TIME_COL}' и/или '{LEVEL_COL}'. " + f"Найденные столбцы: {reader.fieldnames}" + ) + + # Проходим по всем строкам после заголовка + for row in reader: + # Время + t = float(row[TIME_COL]) + # Уровень (0 или 1) + lvl = int(row[LEVEL_COL]) + + times.append(t) + levels.append(lvl) + + if not times: + raise RuntimeError("CSV пустой или не содержит данных (только заголовок).") + + return times, levels + + +# ========================== +# ПОСТРОЕНИЕ СЕГМЕНТОВ +# ========================== + +def build_segments(times, levels): + """ + Строит сегменты постоянного уровня. + + На входе: + times[i], levels[i] — выборки (временная метка + уровень). + + На выходе: + segments: список кортежей (level, duration_sec), где: + level — 0 или 1, + duration_sec — длительность в секундах (> 0). + + Пример: + times = [0.0, 1e-6, 2e-6, 3e-6] + levels = [0, 0, 1, 1 ] + + → segments = [(0, 2e-6), (1, 1e-6)] + """ + segments = [] + + current_level = levels[0] + start_time = times[0] + + # Идём по всем точкам, начиная со второй + for i in range(1, len(times)): + t = times[i] + lvl = levels[i] + + # Если уровень поменялся — значит, закончился сегмент + if lvl != current_level: + duration = t - start_time + if duration > 0: + segments.append((current_level, duration)) + # Начинаем новый сегмент с новым уровнем + start_time = t + current_level = lvl + + # Последний сегмент: от последней смены до конца записи + end_time = times[-1] + duration = end_time - start_time + if duration > 0: + segments.append((current_level, duration)) + + # Если ни одного сегмента не получилось (например, уровень вообще не менялся) + if not segments: + full_duration = times[-1] - times[0] + if full_duration <= 0: + raise RuntimeError("Не удалось построить сегменты: время не растёт.") + segments.append((levels[0], full_duration)) + + return segments + + +# ========================== +# КВАНТОВАНИЕ В ТИКИ +# ========================== + +def quantize_segments(segments, f_clk_hz: float): + """ + Переводит длительность сегментов из секунд в количество тиков таймера. + + На входе: + segments: список (level, duration_sec) + + На выходе: + segments_ticks: список (level, ticks) + ticks — целое положительное число (>= 1) + """ + result = [] + + for idx, (level, duration_sec) in enumerate(segments): + # Перевод секунд в тики + ticks = round(duration_sec * f_clk_hz) + + # Страховка от нулевой длительности + if ticks <= 0: + ticks = 1 + + result.append((level, ticks)) + + return result + + +# ========================== +# ГЕНЕРАЦИЯ VERILOG ROM +# ========================== + +def generate_verilog_rom(segments_ticks, out_path: str): + """ + Генерирует Verilog-модуль pattern_rom с ROM вида: + data = {level, ticks}, где + level — самый старший бит (1 бит), + ticks — младшие TICKS_WIDTH бит. + + Интерфейс модуля: + module pattern_rom #( + parameter TICKS_WIDTH = ..., + parameter DEPTH = ... + )( + input wire [$clog2(DEPTH)-1:0] addr, + output reg [TICKS_WIDTH:0] data + ); + + // data[TICKS_WIDTH] - уровень (0 или 1) + // data[TICKS_WIDTH-1:0] - ticks + """ + depth = len(segments_ticks) + + lines = [] + lines.append(f"// Автогенерация из CSV: {CSV_FILE}") + lines.append(f"// F_CLK_HZ = {F_CLK_HZ}") + lines.append(f"// Количество сегментов (DEPTH) = {depth}") + lines.append("") + lines.append("module pattern_rom #(") + lines.append(f" parameter TICKS_WIDTH = {TICKS_WIDTH},") + lines.append(f" parameter DEPTH = {depth}") + lines.append(") (") + lines.append(" input wire [$clog2(DEPTH)-1:0] addr,") + lines.append(" output reg [TICKS_WIDTH:0] data // {level[MSB], ticks[LSB:0]}") + lines.append(");") + lines.append("") + lines.append(" // Простейший ROM на case по адресу") + lines.append(" always @* begin") + lines.append(" case (addr)") + + for i, (level, ticks) in enumerate(segments_ticks): + # Проверяем, помещается ли длительность в TICKS_WIDTH бит + if ticks >= (1 << TICKS_WIDTH): + raise ValueError( + f"Сегмент {i}: ticks={ticks} не помещается в {TICKS_WIDTH} бит. " + "Увеличьте TICKS_WIDTH или уменьшите F_CLK_HZ." + ) + + # Строка ROM: + # i: data = {1'bL, TICKS_WIDTH'dticks}; + lines.append( + f" {i}: data = {{1'b{level}, {TICKS_WIDTH}'d{ticks}}};" + ) + + # Значение по умолчанию (на всякий случай) + lines.append(" default: data = {1'b0, {TICKS_WIDTH{1'b0}}};") + lines.append(" endcase") + lines.append(" end") + lines.append("endmodule") + lines.append("") + + # Запись Verilog-файла + Path(out_path).write_text("\n".join(lines), encoding="utf-8") + + +# ========================== +# ТОЧКА ВХОДА +# ========================== + +def main(): + # 1. Читаем CSV Logic 2 + times, levels = read_digital_trace(CSV_FILE) + + # 2. Строим сегменты постоянного уровня + segments = build_segments(times, levels) + + # 3. Переводим длительность сегментов в тики тактового генератора + segments_ticks = quantize_segments(segments, F_CLK_HZ) + + # 4. Генерируем Verilog ROM + generate_verilog_rom(segments_ticks, VERILOG_FILE) + + # Немного статистики в консоль + print(f"OK: прочитано выборок: {len(times)}") + print(f" построено сегментов: {len(segments_ticks)}") + print(f" Verilog ROM записан: {VERILOG_FILE}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/top.v b/top.v new file mode 100644 index 0000000..23a0ce8 --- /dev/null +++ b/top.v @@ -0,0 +1,53 @@ +// top.v — верхний уровень для Cyclone IV (OMDAZZ) +// Внутри — pattern_player + pattern_rom (ROM сгенерирован Python-скриптом) + +module top ( + input wire CLK50, // системный клок с платы (например, 50 МГц) + input wire KEY0, // кнопка reset (на OMDAZZ часто активный низ) + output wire GPIO0 // выход на пин (оптопара/LED и т.п.) +); + + // ========================== + // Сброс (reset) + // ========================== + // Предположим, что KEY0 замыкает на 0, когда нажата → делаем rst = !KEY0. + wire rst = ~KEY0; + + // ========================== + // Сигнал запуска плеера + // ========================== + // Для начала можем просто держать start = 1, + // чтобы паттерн проигрывался один раз после сброса. + // Если нужен запуск по кнопке — можно сделать простую логіку отдельно. + wire start = 1'b1; + + // ========================== + // Параметры должны совпадать с pattern_rom.v + // ========================== + localparam TICKS_WIDTH = 32; + // DEPTH возьми из комментария в созданном pattern_rom.v + // (Python-скрипт его печатает). Например: + localparam DEPTH = 128; + + // ========================== + // Соединения с pattern_player + // ========================== + wire out_sig; + wire busy; + + pattern_player #( + .TICKS_WIDTH(TICKS_WIDTH), + .DEPTH(DEPTH) + ) u_player ( + .clk (CLK50), // тот же клок, что и в Python (F_CLK_HZ = 50e6) + // если F_CLK_HZ другое — нужен PLL и другой сигнал clk + .rst (rst), + .start (start), + .out (out_sig), + .busy (busy) + ); + + // Выводим сигнал на внешний пин + assign GPIO0 = out_sig; + +endmodule \ No newline at end of file