mirror of
https://github.com/MikhaelKaa/zx_cartridge.git
synced 2026-03-16 14:37:57 +03:00
init
This commit is contained in:
parent
ef64772818
commit
2f6216192d
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal 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
3
.gitmodules
vendored
Normal 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
14
FW/src/makefile
Normal 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
55
FW/src/zx_cartrige.v
Normal 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
142
FW/src/zx_cartrige_tb.v
Normal 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 активируется при обращении в нижние 8кб
|
||||||
|
// Условия: 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
31
FW/zx_cartrige.qpf
Normal 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
70
FW/zx_cartrige.qsf
Normal 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
1
HW/altium_libs
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c41200a6ad7d258b53d009f64863589a1fd4ec8b
|
||||||
BIN
HW/src/main.SchDoc
Normal file
BIN
HW/src/main.SchDoc
Normal file
Binary file not shown.
BIN
HW/src/pcb.PcbDoc
Normal file
BIN
HW/src/pcb.PcbDoc
Normal file
Binary file not shown.
1811
HW/zx_cartridge.PrjPCB
Normal file
1811
HW/zx_cartridge.PrjPCB
Normal file
File diff suppressed because it is too large
Load Diff
1
HW/zx_cartridge.PrjPCBStructure
Normal file
1
HW/zx_cartridge.PrjPCBStructure
Normal file
@ -0,0 +1 @@
|
|||||||
|
Record=TopLevelDocument|FileName=main.SchDoc
|
||||||
Loading…
Reference in New Issue
Block a user