This commit is contained in:
MichailKaa 2026-02-17 18:14:59 +03:00
parent ef64772818
commit 2f6216192d
12 changed files with 2139 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/FW/src/*.bak
/FW/src/*.vcd
/HW/src/__Previews/*.SchDocPreview
/FW/output_files
/FW/incremental_db
/FW/db
/HW/History
/FW/*.qws
/HW/Project Logs for fix/*.LOG
/HW/Project Logs for zx_cartridge/*.LOG
/FW/zx_cartrige_description.txt

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "HW/altium_libs"]
path = HW/altium_libs
url = https://github.com/MikhaelKaa/altium_libs.git

14
FW/src/makefile Normal file
View File

@ -0,0 +1,14 @@
# Для тестирования модуля неодходимо чтобы тест назывался %имя_модуля%_tb
TARGET ?= zx_cartrige
ICARUS = iverilog
all:
rm -f $(TARGET)
$(ICARUS) -g2012 -o $(TARGET) $(TARGET).v $(TARGET)_tb.v
vvp $(TARGET)
rm -f $(TARGET)
clean:
rm -f $(TARGET) $(TARGET).vcd
.PHONY: all clean

55
FW/src/zx_cartrige.v Normal file
View File

@ -0,0 +1,55 @@
`timescale 1ns / 1ps
// ZX SPECTRUM cartrige module
// 17.02.2026 Mikhael Kaa
// CPU adr bus A0...A12 connect directly to CR_ROM chip
module zx_cartrige #(
// default example parameter
parameter SELF_LOCK_VAL = 10
)(
// Reset
input reset_n,
// CPU ctrl signals
input iorq_n,
input rd_n,
input mreq_n,
// Part of CPU adr bus
input A7,
input A13,
input A14,
input A15,
// ZX ROM block
output ZX_ROM_blk,
// Cartrige ROM enable
output CR_ROM_oe_n,
// Up part cartrige ROM adr bus (A13...A18)
output [5:0] CR_ROM_A
);
// CR_ROM 8kb bank counter
reg [5:0] CR_ROM_bank_cnt = 6'b0;
// Self lock register, disable all logic and CR_ROM
reg self_lock = 1'b0;
// rd or wr port 0x7f increment CR_ROM bank
wire rom_page_up = iorq_n | A7 | self_lock;
// CPU work with 0000...1fff adr
wire lower_rom = ({A13, A14, A15} == 3'b000) ? 1'b1 : 1'b0;
always @(negedge rom_page_up or negedge reset_n) begin
if(!reset_n) begin
CR_ROM_bank_cnt <= 6'b0;
self_lock <= 1'b0;
end else begin
// increment bank counter
CR_ROM_bank_cnt <= CR_ROM_bank_cnt + 1'b1;
// check self lock
if(CR_ROM_bank_cnt == SELF_LOCK_VAL) begin
self_lock <= 1'b1;
end
end
end
assign CR_ROM_oe_n = ~lower_rom | rd_n | mreq_n | self_lock ;
assign ZX_ROM_blk = ~CR_ROM_oe_n;
assign CR_ROM_A = CR_ROM_bank_cnt;
endmodule

142
FW/src/zx_cartrige_tb.v Normal file
View File

@ -0,0 +1,142 @@
`timescale 1ns / 1ps
module tb_zx_cartrige();
reg reset_n;
reg iorq_n;
reg rd_n;
reg mreq_n;
reg A7, A13, A14, A15;
wire ZX_ROM_blk;
wire CR_ROM_oe_n;
wire [5:0] CR_ROM_A;
// DUT с уменьшенным параметром для быстрой проверки
zx_cartrige #(
.SELF_LOCK_VAL(3)
) uut (
.reset_n(reset_n),
.iorq_n(iorq_n),
.rd_n(rd_n),
.mreq_n(mreq_n),
.A7(A7),
.A13(A13),
.A14(A14),
.A15(A15),
.ZX_ROM_blk(ZX_ROM_blk),
.CR_ROM_oe_n(CR_ROM_oe_n),
.CR_ROM_A(CR_ROM_A)
);
initial begin
$dumpfile("tb_zx_cartrige.vcd");
$dumpvars(0, tb_zx_cartrige);
// Исходное состояние: сброс активен
reset_n = 0;
iorq_n = 1;
rd_n = 1;
mreq_n = 1;
A7 = 0;
A13 = 0;
A14 = 0;
A15 = 0;
#100;
reset_n = 1;
#10;
// ------------------------------------------------------------
// Test 1: Инкремент происходит только при A7=0 и спаде iorq_n
// ------------------------------------------------------------
$display("=== Test 1: Increment condition (A7=0 and iorq_n falling) ===");
if (CR_ROM_A !== 0) $display("ERROR: Initial CR_ROM_A = %d, expected 0", CR_ROM_A);
// Попытка инкремента с A7=1 не должен инкрементироваться
A7 = 1;
iorq_n = 0; // rom_page_up = 0|1|0 = 1 нет изменения
#10;
iorq_n = 1;
#10;
if (CR_ROM_A !== 0) $display("ERROR: Increment occurred while A7=1, CR_ROM_A = %d", CR_ROM_A);
// Теперь A7=0, создаём отрицательный фронт iorq_n
A7 = 0;
iorq_n = 1;
#10;
iorq_n = 0; // rom_page_up: 1->0 -> negedge
#10;
if (CR_ROM_A !== 1) $display("ERROR: No increment when A7=0 and iorq_n falling, CR_ROM_A = %d", CR_ROM_A);
iorq_n = 1;
#10;
// ------------------------------------------------------------
// Test 2: Достижение SELF_LOCK_VAL блокирует активацию CR_ROM_oe_n
// ------------------------------------------------------------
$display("=== Test 2: Self-lock prevents CR_ROM_oe_n activation ===");
// Инкрементируем до 2
iorq_n = 0; #10; iorq_n = 1; #10; // CR_ROM_A=2
iorq_n = 0; #10; iorq_n = 1; #10; // CR_ROM_A=3 (lock)
if (CR_ROM_A !== 3) $display("ERROR: Failed to reach lock, CR_ROM_A = %d", CR_ROM_A);
// self_lock активен. Проверим, что CR_ROM_oe_n всегда 1 при попытке активации
// Необходимые условия: lower_rom=1 (A13=A14=A15=0), rd_n=0, mreq_n=0
A13 = 0; A14 = 0; A15 = 0;
rd_n = 0;
mreq_n = 0;
#10;
if (CR_ROM_oe_n !== 0) $display("ERROR: CR_ROM_oe_n = %b, expected 1 (self_lock active)", CR_ROM_oe_n);
if (ZX_ROM_blk !== 1) $display("ERROR: ZX_ROM_blk = %b, expected 0", ZX_ROM_blk);
rd_n = 1; mreq_n = 1;
#10;
// ------------------------------------------------------------
// Test 3: CR_ROM_oe_n активируется при обращении в нижние б
// Условия: lower_rom=1, rd_n=0, mreq_n=0, self_lock=0
// ------------------------------------------------------------
$display("=== Test 3: CR_ROM_oe_n activation in lower ROM area ===");
// Сброс для снятия self_lock
reset_n = 0;
#10;
reset_n = 1;
#10;
if (CR_ROM_A !== 0) $display("ERROR: After reset CR_ROM_A = %d, expected 0", CR_ROM_A);
// Устанавливаем условия для активации
A13 = 0; A14 = 0; A15 = 0; // lower_rom = 1
rd_n = 0;
mreq_n = 0;
#10;
// Ожидаем CR_ROM_oe_n = 0 (активен)
if (CR_ROM_oe_n !== 0) $display("ERROR: CR_ROM_oe_n = %b, expected 0 during lower ROM access (rd_n=0, mreq_n=0)", CR_ROM_oe_n);
if (ZX_ROM_blk !== 1) $display("ERROR: ZX_ROM_blk = %b, expected 1", ZX_ROM_blk);
// Проверка, что при выходе из нижней области (lower_rom=0) выход отключается
A13 = 1; // теперь lower_rom = 0 (A13=1, остальные 0)
#10;
if (CR_ROM_oe_n !== 1) $display("ERROR: CR_ROM_oe_n = %b, expected 1 when not in lower ROM", CR_ROM_oe_n);
// Проверка, что при rd_n=1 выход отключается
A13 = 0; // обратно в lower_rom=1
rd_n = 1;
#10;
if (CR_ROM_oe_n !== 1) $display("ERROR: CR_ROM_oe_n = %b, expected 1 when rd_n=1", CR_ROM_oe_n);
// Проверка, что при mreq_n=1 выход отключается
rd_n = 0; mreq_n = 1;
#10;
if (CR_ROM_oe_n !== 1) $display("ERROR: CR_ROM_oe_n = %b, expected 1 when mreq_n=1", CR_ROM_oe_n);
rd_n = 1; mreq_n = 1;
#10;
$display("=== All tests completed ===");
$finish;
end
endmodule

31
FW/zx_cartrige.qpf Normal file
View File

@ -0,0 +1,31 @@
# -------------------------------------------------------------------------- #
#
# 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.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
# Date created = 17:08:17 February 17, 2026
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "13.0"
DATE = "17:08:17 February 17, 2026"
# Revisions
PROJECT_REVISION = "zx_cartrige"
PROJECT_REVISION = "d_fix"

70
FW/zx_cartrige.qsf Normal file
View File

@ -0,0 +1,70 @@
# -------------------------------------------------------------------------- #
#
# 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.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
# Date created = 14:32:59 February 06, 2026
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# d_fix_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 MAX7000S
set_global_assignment -name DEVICE "EPM7064SLC44-10"
set_global_assignment -name TOP_LEVEL_ENTITY zx_cartrige
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "14:32:59 FEBRUARY 06, 2026"
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name DEVICE_FILTER_PACKAGE PLCC
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 44
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 10
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1"
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name MAX7000_DEVICE_IO_STANDARD TTL
set_location_assignment PIN_1 -to reset_n
set_global_assignment -name VERILOG_FILE src/zx_cartrige.v
set_global_assignment -name CDF_FILE output_files/Chain1.cdf
set_location_assignment PIN_18 -to A7
set_location_assignment PIN_19 -to A13
set_location_assignment PIN_20 -to A14
set_location_assignment PIN_21 -to A15
set_location_assignment PIN_31 -to CR_ROM_A[5]
set_location_assignment PIN_29 -to CR_ROM_A[4]
set_location_assignment PIN_28 -to CR_ROM_A[3]
set_location_assignment PIN_9 -to CR_ROM_A[2]
set_location_assignment PIN_11 -to CR_ROM_A[1]
set_location_assignment PIN_12 -to CR_ROM_A[0]
set_location_assignment PIN_34 -to CR_ROM_oe_n
set_location_assignment PIN_27 -to ZX_ROM_blk
set_location_assignment PIN_24 -to iorq_n
set_location_assignment PIN_25 -to mreq_n
set_location_assignment PIN_26 -to rd_n

1
HW/altium_libs Submodule

@ -0,0 +1 @@
Subproject commit c41200a6ad7d258b53d009f64863589a1fd4ec8b

BIN
HW/src/main.SchDoc Normal file

Binary file not shown.

BIN
HW/src/pcb.PcbDoc Normal file

Binary file not shown.

1811
HW/zx_cartridge.PrjPCB Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
Record=TopLevelDocument|FileName=main.SchDoc