Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c2ec790a7 | |||
| 0d5e47f74a | |||
| 514814e555 | |||
| 37f31f7dcb | |||
| 5ec983c2bd | |||
| 0cac4b916a | |||
| 940920d18b |
6
.gitignore
vendored
6
.gitignore
vendored
@ -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
101
Logic2_D7.csv
Normal 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
|
||||
|
30
Logic2_to_FPGA.qpf
Normal file
30
Logic2_to_FPGA.qpf
Normal 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
107
Logic2_to_FPGA.qsf
Normal 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
1614074
digital.csv
Normal file
File diff suppressed because it is too large
Load Diff
52
digital_cut_50.csv
Normal file
52
digital_cut_50.csv
Normal 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
|
||||
|
25
error.txt
Normal file
25
error.txt
Normal 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
3
omdazz.sdc
Normal file
@ -0,0 +1,3 @@
|
||||
create_clock -period 20.0 -name CLK50 [get_ports CLK50]
|
||||
|
||||
|
||||
22
output_file.cof
Normal file
22
output_file.cof
Normal 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
82
pattern_player.v
Normal 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
69
pattern_rom.v
Normal 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
93
stp2.stp
Normal 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
244
to_FPGA.py
Normal 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
59
top.v
Normal 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
|
||||
BIN
схема платы плис V2.5.pdf
Normal file
BIN
схема платы плис V2.5.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user