Compare commits

..

7 Commits
main ... master

Author SHA1 Message Date
6c2ec790a7 added схема платы плис V2.5.pdf 2026-06-01 22:16:15 +03:00
0d5e47f74a added error.txt 2026-06-01 22:14:32 +03:00
514814e555 added stp2.stp 2026-06-01 21:50:55 +03:00
37f31f7dcb added real data 2026-06-01 16:41:22 +03:00
5ec983c2bd added digital.csv 2026-06-01 17:39:57 +03:00
0cac4b916a create_clock -period 20 -name CLK50 [get_ports CLK50] 2026-06-01 06:39:06 +03:00
940920d18b added files 2026-06-01 06:19:27 +03:00
15 changed files with 1614967 additions and 0 deletions

6
.gitignore vendored
View File

@ -102,6 +102,12 @@
*.html
*/*/bd/*/ip/*/*.tcl
*/*/*/bd/*/ip/*/*.tcl
db/
incremental_db/
output_files/
*.sof
*.pof
*.qws
hw_handoff
ipshared

101
Logic2_D7.csv Normal file
View File

@ -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
1 Time [s] D7
2 0.0000000000000000 0
3 0.0000000010000000 0
4 0.0000000020000000 1
5 0.0000000030000000 1
6 0.0000000040000000 0
7 0.0000000050000000 0
8 0.0000000060000000 1
9 0.0000000070000000 1
10 0.0000000080000000 0
11 0.0000000090000000 0
12 0.0000000100000000 1
13 0.0000000110000000 1
14 0.0000000120000000 0
15 0.0000000130000000 0
16 0.0000000140000000 1
17 0.0000000150000000 1
18 0.0000000160000000 0
19 0.0000000170000000 0
20 0.0000000180000000 1
21 0.0000000190000000 1
22 0.0000000200000000 0
23 0.0000000210000000 0
24 0.0000000220000000 1
25 0.0000000230000000 1
26 0.0000000240000000 0
27 0.0000000250000000 0
28 0.0000000260000000 1
29 0.0000000270000000 1
30 0.0000000280000000 0
31 0.0000000290000000 0
32 0.0000000300000000 1
33 0.0000000310000000 1
34 0.0000000320000000 0
35 0.0000000330000000 0
36 0.0000000340000000 1
37 0.0000000350000000 1
38 0.0000000360000000 0
39 0.0000000370000000 0
40 0.0000000380000000 1
41 0.0000000390000000 1
42 0.0000000400000000 0
43 0.0000000410000000 0
44 0.0000000420000000 1
45 0.0000000430000000 1
46 0.0000000440000000 0
47 0.0000000450000000 0
48 0.0000000460000000 1
49 0.0000000470000000 1
50 0.0000000480000000 0
51 0.0000000490000000 0
52 0.0000000500000000 1
53 0.0000000510000000 1
54 0.0000000520000000 0
55 0.0000000530000000 0
56 0.0000000540000000 1
57 0.0000000550000000 1
58 0.0000000560000000 0
59 0.0000000570000000 0
60 0.0000000580000000 1
61 0.0000000590000000 1
62 0.0000000600000000 0
63 0.0000000610000000 0
64 0.0000000620000000 1
65 0.0000000630000000 1
66 0.0000000640000000 0
67 0.0000000650000000 0
68 0.0000000660000000 1
69 0.0000000670000000 1
70 0.0000000680000000 0
71 0.0000000690000000 0
72 0.0000000700000000 1
73 0.0000000710000000 1
74 0.0000000720000000 0
75 0.0000000730000000 0
76 0.0000000740000000 1
77 0.0000000750000000 1
78 0.0000000760000000 0
79 0.0000000770000000 0
80 0.0000000780000000 1
81 0.0000000790000000 1
82 0.0000000800000000 0
83 0.0000000810000000 0
84 0.0000000820000000 1
85 0.0000000830000000 1
86 0.0000000840000000 0
87 0.0000000850000000 0
88 0.0000000860000000 1
89 0.0000000870000000 1
90 0.0000000880000000 0
91 0.0000000890000000 0
92 0.0000000900000000 1
93 0.0000000910000000 1
94 0.0000000920000000 0
95 0.0000000930000000 0
96 0.0000000940000000 1
97 0.0000000950000000 1
98 0.0000000960000000 0
99 0.0000000970000000 0
100 0.0000000980000000 1
101 0.0000000990000000 1

30
Logic2_to_FPGA.qpf Normal file
View File

@ -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"

107
Logic2_to_FPGA.qsf Normal file
View File

@ -0,0 +1,107 @@
# -------------------------------------------------------------------------- #
#
# 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_88 -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_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
set_instance_assignment -name SLEW_RATE 2 -to GPIO0
set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE stp2.stp
set_global_assignment -name SLD_NODE_CREATOR_ID 110 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_ENTITY_NAME sld_signaltap -section_id auto_signaltap_0
set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT acq_clk -to CLK50 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_RAM_BLOCK_TYPE=AUTO" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_INFO=805334528" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_POWER_UP_TRIGGER=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ATTRIBUTE_MEM_MODE=OFF" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STATE_FLOW_USE_GENERATED=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STATE_BITS=11" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_BUFFER_FULL_STOP=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_CURRENT_RESOURCE_WIDTH=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_LEVEL=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ADVANCED_TRIGGER_ENTITY=basic,1," -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_LEVEL_PIPELINE=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ENABLE_ADVANCED_TRIGGER=0" -section_id auto_signaltap_0
set_global_assignment -name SIGNALTAP_FILE stp2.stp
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STORAGE_QUALIFIER_INVERSION_MASK_LENGTH=0" -section_id auto_signaltap_0
set_location_assignment PIN_84 -to GPIO1
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO1
set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT trigger_in -to clk50_div2 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_IN_ENABLED=1" -section_id auto_signaltap_0
set_instance_assignment -name SLEW_RATE 2 -to GPIO1
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_SEGMENT_SIZE=131072" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_SAMPLE_DEPTH=131072" -section_id auto_signaltap_0
set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[0] -to clk50_div2 -section_id auto_signaltap_0
set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[0] -to clk50_div2 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_DATA_BITS=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_BITS=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_INVERSION_MASK=0000000000000000000000000000000000" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_INVERSION_MASK_LENGTH=34" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_CRC_LOWORD=44983" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_CRC_HIWORD=43530" -section_id auto_signaltap_0
set_global_assignment -name SLD_FILE db/stp2_auto_stripped.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

1614074
digital.csv Normal file

File diff suppressed because it is too large Load Diff

52
digital_cut_50.csv Normal file
View File

@ -0,0 +1,52 @@
Time [s],Channel 7
0.000000000,0
0.000085333,1
0.000085625,0
0.000085833,1
0.000086000,0
0.000086417,1
0.000086583,0
0.000087000,1
0.000087167,0
0.000087625,1
0.000088042,0
0.000088208,1
0.000088625,0
0.000088833,1
0.000089000,0
0.000089417,1
0.000089583,0
0.000090000,1
0.000090417,0
0.000090625,1
0.000091042,0
0.000091208,1
0.000091625,0
0.000091833,1
0.000092000,0
0.000092417,1
0.000092833,0
0.000093000,1
0.000093167,0
0.000093625,1
0.000093792,0
0.000094208,1
0.000094375,0
0.000094833,1
0.000095208,0
0.000095417,1
0.000095833,0
0.000096000,1
0.000096167,0
0.000096625,1
0.000096792,0
0.000097208,1
0.000097625,0
0.000097833,1
0.000098208,0
0.000098417,1
0.000098833,0
0.000099000,1
0.000099167,0
0.000099583,1
0.000100167,0
1 Time [s] Channel 7
2 0.000000000 0
3 0.000085333 1
4 0.000085625 0
5 0.000085833 1
6 0.000086000 0
7 0.000086417 1
8 0.000086583 0
9 0.000087000 1
10 0.000087167 0
11 0.000087625 1
12 0.000088042 0
13 0.000088208 1
14 0.000088625 0
15 0.000088833 1
16 0.000089000 0
17 0.000089417 1
18 0.000089583 0
19 0.000090000 1
20 0.000090417 0
21 0.000090625 1
22 0.000091042 0
23 0.000091208 1
24 0.000091625 0
25 0.000091833 1
26 0.000092000 0
27 0.000092417 1
28 0.000092833 0
29 0.000093000 1
30 0.000093167 0
31 0.000093625 1
32 0.000093792 0
33 0.000094208 1
34 0.000094375 0
35 0.000094833 1
36 0.000095208 0
37 0.000095417 1
38 0.000095833 0
39 0.000096000 1
40 0.000096167 0
41 0.000096625 1
42 0.000096792 0
43 0.000097208 1
44 0.000097625 0
45 0.000097833 1
46 0.000098208 0
47 0.000098417 1
48 0.000098833 0
49 0.000099000 1
50 0.000099167 0
51 0.000099583 1
52 0.000100167 0

25
error.txt Normal file
View File

@ -0,0 +1,25 @@
Error (265013): Can't open SignalTap II Logic Analyzer. Verify that the license file exists and is stored in the correct location. If you are using the Quartus II Web Edition software, you must turn on the TalkBack feature to use the SignalTap II Logic Analyzer.
Выполнено 2 шага
Сообщение говорит, что Quartus не даёт запустить SignalTap, потому что для твоей редакции нужна включённая «телеметрия» (TalkBack) и корректная лицензия.
Если у тебя Quartus II Web Edition или Quartus Prime Lite
Для Web / Lite SignalTap работает только при включённом TalkBack:
Включить TalkBack:
Меню Tools → Options.
В дереве слева выбрать Internet Connectivity.
Нажать кнопку TalkBack Options….
Поставить галку «Turn on the Quartus II software TalkBack feature» или «Enable sending TalkBack data to Altera / Intel».
Нажать OK, потом ещё раз OK, чтобы выйти из Options.
Перезапустить Quartus и проект, затем:
Снова попробовать открыть Tools → SignalTap II Logic Analyzer.
При необходимости пересобрать проект, потому что при отключённом TalkBack SignalTap не встраивался.

3
omdazz.sdc Normal file
View File

@ -0,0 +1,3 @@
create_clock -period 20.0 -name CLK50 [get_ports CLK50]

22
output_file.cof Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<cof>
<eprom_name>EPCS4</eprom_name>
<flash_loader_device>EP4CE6</flash_loader_device>
<output_filename>output_file.jic</output_filename>
<n_pages>1</n_pages>
<width>1</width>
<mode>7</mode>
<sof_data>
<user_name>Page_0</user_name>
<page_flags>1</page_flags>
<bit0>
<sof_filename>C:/Users/irobo/PycharmProjects/Logic2_to_FPGA/output_files/Logic2_to_FPGA.sof</sof_filename>
</bit0>
</sof_data>
<version>5</version>
<create_cvp_file>0</create_cvp_file>
<auto_create_rpd>0</auto_create_rpd>
<options>
<map_file>1</map_file>
</options>
</cof>

82
pattern_player.v Normal file
View File

@ -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

69
pattern_rom.v Normal file
View File

@ -0,0 +1,69 @@
// Автогенерация из CSV: digital_cut_50.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'd4096};
1: data = {1'b1, 32'd14};
2: data = {1'b0, 32'd10};
3: data = {1'b1, 32'd8};
4: data = {1'b0, 32'd20};
5: data = {1'b1, 32'd8};
6: data = {1'b0, 32'd20};
7: data = {1'b1, 32'd8};
8: data = {1'b0, 32'd22};
9: data = {1'b1, 32'd20};
10: data = {1'b0, 32'd8};
11: data = {1'b1, 32'd20};
12: data = {1'b0, 32'd10};
13: data = {1'b1, 32'd8};
14: data = {1'b0, 32'd20};
15: data = {1'b1, 32'd8};
16: data = {1'b0, 32'd20};
17: data = {1'b1, 32'd20};
18: data = {1'b0, 32'd10};
19: data = {1'b1, 32'd20};
20: data = {1'b0, 32'd8};
21: data = {1'b1, 32'd20};
22: data = {1'b0, 32'd10};
23: data = {1'b1, 32'd8};
24: data = {1'b0, 32'd20};
25: data = {1'b1, 32'd20};
26: data = {1'b0, 32'd8};
27: data = {1'b1, 32'd8};
28: data = {1'b0, 32'd22};
29: data = {1'b1, 32'd8};
30: data = {1'b0, 32'd20};
31: data = {1'b1, 32'd8};
32: data = {1'b0, 32'd22};
33: data = {1'b1, 32'd18};
34: data = {1'b0, 32'd10};
35: data = {1'b1, 32'd20};
36: data = {1'b0, 32'd8};
37: data = {1'b1, 32'd8};
38: data = {1'b0, 32'd22};
39: data = {1'b1, 32'd8};
40: data = {1'b0, 32'd20};
41: data = {1'b1, 32'd20};
42: data = {1'b0, 32'd10};
43: data = {1'b1, 32'd18};
44: data = {1'b0, 32'd10};
45: data = {1'b1, 32'd20};
46: data = {1'b0, 32'd8};
47: data = {1'b1, 32'd8};
48: data = {1'b0, 32'd20};
49: data = {1'b1, 32'd28};
default: data = {1'b0, {TICKS_WIDTH{1'b0}}};
endcase
end
endmodule

93
stp2.stp Normal file
View File

@ -0,0 +1,93 @@
<session jtag_chain="USB-Blaster [USB-0]" jtag_device="@1: EP3C(10|5)/EP4CE(10|6) (0x020F10DD)" sof_file="">
<display_tree gui_logging_enabled="0">
<display_branch instance="auto_signaltap_0" log="USE_GLOBAL_TEMP" signal_set="USE_GLOBAL_TEMP" trigger="USE_GLOBAL_TEMP"/>
</display_tree>
<mnemonics/>
<static_plugin_mnemonics/>
<instance entity_name="sld_signaltap" is_auto_node="yes" is_expanded="true" name="auto_signaltap_0" source_file="sld_signaltap.vhd">
<node_ip_info instance_id="0" mfg_id="110" node_id="0" version="6"/>
<position_info>
<single attribute="active tab" value="1"/>
<single attribute="data horizontal scroll position" value="7"/>
<single attribute="data vertical scroll position" value="0"/>
<single attribute="zoom level denominator" value="1"/>
<single attribute="zoom level numerator" value="8"/>
<single attribute="zoom offset denominator" value="1"/>
<single attribute="zoom offset numerator" value="16368"/>
</position_info>
<signal_set global_temp="1" name="signal_set: 2026/06/01 22:10:31 #0">
<clock name="CLK50" polarity="posedge" tap_mode="probeonly"/>
<config is_hps_trigger_out_selected="false" ram_type="AUTO" reserved_data_nodes="0" reserved_storage_qualifier_nodes="0" reserved_trigger_nodes="0" sample_depth="131072" trigger_in_enable="yes" trigger_in_node="clk50_div2" trigger_in_tap_mode="probeonly" trigger_out_enable="no"/>
<top_entity/>
<signal_vec>
<trigger_input_vec>
<wire name="clk50_div2" tap_mode="probeonly"/>
</trigger_input_vec>
<data_input_vec>
<wire name="clk50_div2" tap_mode="probeonly"/>
</data_input_vec>
<storage_qualifier_input_vec>
<wire name="clk50_div2" tap_mode="probeonly"/>
</storage_qualifier_input_vec>
</signal_vec>
<presentation>
<unified_setup_data_view>
<node data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="clk50_div2" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="probeonly" trigger_index="0" type="unknown"/>
</unified_setup_data_view>
<data_view>
<net data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="clk50_div2" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="probeonly" trigger_index="0" type="unknown"/>
</data_view>
<setup_view>
<net data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="clk50_div2" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="probeonly" trigger_index="0" type="unknown"/>
</setup_view>
<trigger_in_editor is_enabled="true" is_node_post_fitting="true" node_name="clk50_div2"/>
<trigger_out_editor/>
</presentation>
<trigger attribute_mem_mode="false" gap_record="true" global_temp="1" name="trigger: 2026/06/01 22:10:31 #1" position="pre" power_up_trigger_mode="false" record_data_gap="true" segment_size="64" storage_mode="off" storage_qualifier_disabled="no" storage_qualifier_port_is_pin="false" storage_qualifier_port_name="auto_stp_external_storage_qualifier" storage_qualifier_port_tap_mode="classic" trigger_in="high" trigger_type="circular">
<power_up_trigger position="pre" storage_qualifier_disabled="no" trigger_in="high"/>
<events use_custom_flow_control="no">
<level enabled="yes" name="condition1" type="basic">
<power_up enabled="yes">
</power_up>
<op_node/>
</level>
</events>
<storage_qualifier_events>
<transitional>1
<pwr_up_transitional>1</pwr_up_transitional>
</transitional>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
</storage_qualifier_events>
<log>
<data global_temp="1" name="log: 2026/06/01 22:10:31 #2"/>
<extradata/>
</log>
</trigger>
</signal_set>
</instance>
<global_info>
<single attribute="active instance" value="0"/>
<single attribute="config widget visible" value="1"/>
<single attribute="data log widget visible" value="1"/>
<single attribute="hierarchy widget height" value="95"/>
<single attribute="hierarchy widget visible" value="1"/>
<single attribute="instance widget visible" value="1"/>
<single attribute="jtag widget visible" value="1"/>
<multi attribute="frame size" size="2" value="1024,705"/>
<multi attribute="jtag widget size" size="2" value="334,169"/>
</global_info>
</session>

244
to_FPGA.py Normal file
View File

@ -0,0 +1,244 @@
import csv
from pathlib import Path
# ==========================
# НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ
# ==========================
# Входной файл из Logic 2 (CSV только с Time [s] и D7)
CSV_FILE = "digital_cut_50.csv"
# Выходной Verilog-файл
VERILOG_FILE = "pattern_rom.v"
# Тактовая частота в МК/FPGA, Гц (должна совпадать с тем, что реально в железе)
F_CLK_HZ = 48_000_000 # пример: 48 МГц
# Имена колонок в CSV (посмотри заголовок в своём файле и подгони при необходимости)
TIME_COL = "Time [s]" # колонка с временем
LEVEL_COL = "Channel 7" # колонка с уровнем сигнала
# Сколько бит отвести под счётчик тиков в 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()

59
top.v Normal file
View File

@ -0,0 +1,59 @@
// 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 и т.п.)
output wire GPIO1 // ДОП. выход для clk50_div2 (подвесь на свободный пин)
);
// ==========================
// Сброс (reset)
// ==========================
wire rst = ~KEY0;
// ==========================
// Делитель такта CLK50 / 2
// ==========================
reg clk50_div2 = 1'b0;
always @(posedge CLK50 or posedge rst) begin
if (rst)
clk50_div2 <= 1'b0;
else
clk50_div2 <= ~clk50_div2;
end
// ==========================
// Сигнал запуска плеера
// ==========================
wire start = 1'b1;
// ==========================
// Параметры должны совпадать с pattern_rom.v
// ==========================
localparam TICKS_WIDTH = 32;
localparam DEPTH = 128;
// ==========================
// Соединения с pattern_player
// ==========================
wire out_sig;
wire busy;
pattern_player #(
.TICKS_WIDTH(TICKS_WIDTH),
.DEPTH (DEPTH)
) u_player (
.clk (CLK50), // такт 50 МГц
.rst (rst),
.start (start),
.out (out_sig),
.busy (busy)
);
// Выводим сигнал плеера и делитель такта на внешние пины
assign GPIO0 = out_sig;
assign GPIO1 = clk50_div2; // сюда повесь светодиод или щуп
endmodule

Binary file not shown.