1
0
mirror of https://github.com/UzixLS/zx-sizif-128.git synced 2025-07-18 23:01:28 +03:00

update firmware

1. quartus 13 may be used for build now;
2. fix small border offset;
3. fix too fast flashing with attribute bit 7.
This commit is contained in:
UzixLS
2020-08-15 16:24:29 +03:00
parent 1696b14cae
commit 105b24ffa4
5 changed files with 110 additions and 141 deletions

View File

@ -9,7 +9,7 @@ Specifications:
- PAL encoder in CPLD
- Intended to build on 9x15 prototyping board, but may be built on manufactured PCB
To modify and compile CPLD firmware you need Quartus 9.0 SP2.
To modify and compile CPLD firmware you need Quartus 13.0sp1.
To modify schematic and pcb you need Kicad 5.1.4 or newer.
[Some photos](https://cloud.err200.net/index.php/s/73TR85tYZkMm8Ax?path=%2Fsizif-128)

16
cpld/clocks.sdc Normal file
View File

@ -0,0 +1,16 @@
create_clock -period 14.4MHz -name {clk_14mhz} [get_ports {clk14}]
create_clock -period 16MHz -name {clk_16mhz} [get_ports {clk16}]
# clkcpu 3.5
create_generated_clock -name {clkcpu} -divide_by 4 -source [get_ports {clk14}] [get_registers {hc0[1]}]
# int len in turbo = 66
create_generated_clock -name {n_int} -divide_by 64 -source [get_ports {clk14}] [get_registers {n_int~reg0}]
# chroma carrier
create_generated_clock -name {chroma_carrier} -divide_by 6 -source [get_ports {clk16}] [get_registers {*:chroma_gen1|carrier[14]}]
set_false_path -from [get_registers {r~reg0}] -to [get_clocks {clk_16mhz}]
set_false_path -from [get_registers {g~reg0}] -to [get_clocks {clk_16mhz}]
set_false_path -from [get_registers {b~reg0}] -to [get_clocks {clk_16mhz}]
set_false_path -from [get_registers {hsync1}] -to [get_clocks {chroma_carrier}]

View File

@ -29,8 +29,8 @@ module zx_ula(
input [4:0] kd,
input tape_in,
output tape_out,
output beeper,
output reg tape_out,
output reg beeper,
output ay_clk,
output reg ay_bdir,
@ -44,9 +44,8 @@ module zx_ula(
output reg csync
);
wire timings = 0;
wire turbo = 0;
wire [2:0] border;
wire [15:0] xa = {a15, a14, va[13:2], a1, a0};
wire [7:0] xd = vd;
reg n_iorq_delayed;
always @(posedge clkcpu)
@ -58,70 +57,25 @@ wire n_iorq0 = n_iorq | n_iorq_delayed;
localparam H_AREA = 256;
localparam V_AREA = 192;
localparam SCREEN_DELAY = 8;
localparam H_TOTAL = 448;
localparam V_TOTAL = 320;
localparam H_LBORDER_S48 = 32 - SCREEN_DELAY;
localparam H_RBORDER_S48 = 64 + SCREEN_DELAY;
localparam H_BLANK1_S48 = 16;
localparam H_SYNC_S48 = 32;
localparam H_BLANK2_S48 = 48;
localparam H_TOTAL_S48 = H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48 + H_LBORDER_S48;
localparam V_BBORDER_S48 = 56;
localparam V_SYNC_S48 = 8;
localparam V_TBORDER_S48 = 56;
localparam V_TOTAL_S48 = V_AREA + V_BBORDER_S48 + V_SYNC_S48 + V_TBORDER_S48;
reg [`CLOG2(V_TOTAL)-1:0] vc;
reg [`CLOG2(H_TOTAL):0] hc0;
wire [`CLOG2(H_TOTAL)-1:0] hc = hc0[$bits(hc0)-1:1];
localparam H_LBORDER_S128 = 48 - SCREEN_DELAY;
localparam H_RBORDER_S128 = 48 + SCREEN_DELAY;
localparam H_BLANK1_S128 = 28;
localparam H_SYNC_S128 = 32;
localparam H_BLANK2_S128 = 44;
localparam H_TOTAL_S128 = H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128 + H_LBORDER_S128;
localparam V_BBORDER_S128 = 56;
localparam V_SYNC_S128 = 8;
localparam V_TBORDER_S128 = 55;
localparam V_TOTAL_S128 = V_AREA + V_BBORDER_S128 + V_SYNC_S128 + V_TBORDER_S128;
wire hc0_reset = hc0 == (H_TOTAL<<1) - 1'b1 ;
wire vc_reset = vc == V_TOTAL - 1'b1 ;
wire hsync0 = hc[8:5] == 4'b1010;
wire vsync0 = vc[7:3] == 5'b11111;
wire blank = (vc[7:3] == 5'b11111) || (hc[8:6] == 3'b101);
localparam H_LBORDER_PENT = 64 - SCREEN_DELAY;
localparam H_RBORDER_PENT = 64 + SCREEN_DELAY;
localparam H_BLANK1_PENT = 0;
localparam H_SYNC_PENT = 32;
localparam H_BLANK2_PENT = 32;
localparam H_TOTAL_PENT = H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT + H_BLANK2_PENT + H_LBORDER_PENT;
localparam V_BBORDER_PENT = 56;
localparam V_SYNC_PENT = 8;
localparam V_TBORDER_PENT = 64;
localparam V_TOTAL_PENT = V_AREA + V_BBORDER_PENT + V_SYNC_PENT + V_TBORDER_PENT;
reg hsync1;
always @(posedge clk14)
hsync1 = hc[8:5] != 4'b1010;
reg [`CLOG2(`MAX(V_TOTAL_S128, V_TOTAL_PENT))-1:0] vc;
reg [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT)):0] hc0;
wire [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT))-1:0] hc = hc0[$bits(hc0)-1:1];
wire hc0_reset = timings?
hc0 == (H_TOTAL_S128<<1) - 1'b1 :
hc0 == (H_TOTAL_PENT<<1) - 1'b1 ;
wire vc_reset = timings?
vc == V_TOTAL_S128 - 1'b1 :
vc == V_TOTAL_PENT - 1'b1 ;
wire hsync0 = timings?
(hc >= (H_AREA + H_RBORDER_S128 + H_BLANK1_S128)) &&
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128)) :
(hc[8:5] == 4'b1010);
wire vsync0 = timings?
(vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128)) :
(vc[7:3] == 5'b11111) ;
wire blank = timings?
((vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128))) ||
((hc >= (H_AREA + H_RBORDER_S128)) &&
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128))) :
((vc[7:3] == 5'b11111) ||
(hc[8:6] == 3'b101));
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n) begin
hc0 <= 0;
vc <= 0;
end
else if (hc0_reset) begin
always @(posedge clk14) begin
if (hc0_reset) begin
hc0 <= 0;
if (vc_reset) begin
vc <= 0;
@ -135,7 +89,7 @@ always @(posedge clk14 or negedge rst_n) begin
end
end
reg [3:0] blink_cnt;
reg [4:0] blink_cnt;
wire blink = blink_cnt[$bits(blink_cnt)-1];
always @(posedge n_int or negedge rst_n) begin
if (!rst_n)
@ -144,20 +98,8 @@ always @(posedge n_int or negedge rst_n) begin
blink_cnt <= blink_cnt + 1'b1;
end
reg [2:0] border;
reg [7:0] bitmap, attr, bitmap_next, attr_next;
wire pixel = bitmap[7];
always @(posedge clk14) begin
if (hc0[0]) begin
if (blank)
{i, g, r, b} = 4'b0000;
else begin
{g, r, b} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
i = (g | r | b) & attr[6];
end
csync <= ~(vsync0 ^ hsync0);
end
end
reg screen_read;
wire attr_read = screen_read & ~hc0[0];
wire bitmap_read = screen_read & hc0[0];
@ -167,8 +109,7 @@ wire [14:0] screen_addr = attr_read? attr_addr : bitmap_addr;
wire screen_load = (vc < V_AREA) && (hc < H_AREA);
wire screen_show = (vc < V_AREA) && (hc >= SCREEN_DELAY) && (hc < H_AREA + SCREEN_DELAY);
wire screen_update = hc0[3:0] == 4'b1111;
wire border_update = ((screen_load == 0 && screen_show == 0) || (screen_load == 0 && hc0[3:0] == 4'b1111) || (screen_show == 0 && timings == 0))
&& (timings == 0 || hc0[3:0] == 4'b1111);
wire border_update = (screen_load == 0 && hc0[3:0] == 4'b1111) || (screen_show == 0);
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n) begin
@ -198,66 +139,76 @@ always @(posedge clk14 or negedge rst_n) begin
end
end
wire [15:0] xa = {a15, a14, va[13:2], a1, a0};
/* PORT #FE */
wire port_fe_cs = n_m1 == 1 && n_iorq0 == 0 && xa[0] == 0;
reg port_fe_rd;
always @(posedge clk14)
port_fe_rd <= port_fe_cs && n_rd == 0;
wire [7:0] port_fe_data = {1'b1, tape_in, 1'b1, kd[4:0]};
reg [7:0] port_fe;
assign beeper = port_fe[4];
assign tape_out = port_fe[3] ^ tape_in;
assign border = port_fe[2:0];
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n)
port_fe <= 0;
else if (port_fe_cs && n_wr == 0)
port_fe <= vd;
end
/* PORT #7FFD */
wire port_7ffd_cs = n_m1 == 1 && n_iorq0 == 0 && xa[1] == 0 && xa[15] == 0;
reg [7:0] port_7ffd;
wire [2:0] rambank = port_7ffd[2:0];
wire vbank = port_7ffd[3];
wire rombank = port_7ffd[4];
wire lock_7ffd = port_7ffd[5];
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n)
port_7ffd <= 0;
else if (port_7ffd_cs && n_wr == 0 && lock_7ffd == 0)
port_7ffd <= vd;
end
/* INT GENERATOR */
localparam INT_V_S48 = 248;
localparam INT_H_FROM_S48 = 0;
localparam INT_H_TO_S48 = 63;
localparam INT_V_S128 = 248;
localparam INT_H_FROM_S128 = 2;
localparam INT_H_TO_S128 = 65;
localparam INT_V_PENT = 239;
localparam INT_H_FROM_PENT = 320;
localparam INT_H_TO_PENT = 384;
wire pixel = bitmap[7];
always @(posedge clk14) begin
n_int <= timings?
(vc != INT_V_S128 || hc < INT_H_FROM_S128 || hc > INT_H_TO_S128) :
(vc != INT_V_PENT || hc < INT_H_FROM_PENT || hc > INT_H_TO_PENT) ;
if (hc0[0]) begin
if (blank)
{i, g, r, b} = 4'b0000;
else begin
{g, r, b} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
i = (g | r | b) & attr[6];
end
csync <= ~(vsync0 ^ hsync0);
end
end
/* CLOCK */
reg [2:0] clk_cnt;
always @(posedge clk14) begin
clk_cnt <= clk_cnt + 1'b1;
assign clkcpu = hc[0];
/* INT GENERATOR */
localparam INT_V = 239;
localparam INT_H_FROM = 318;
localparam INT_H_TO = 382;
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n)
n_int <= 1;
else
n_int <= vc != INT_V || hc < INT_H_FROM || hc > INT_H_TO ;
end
/* PORT #FE */
wire port_fe_cs = n_m1 == 1 && n_iorq0 == 0 && xa[0] == 0;
wire [7:0] port_fe_data = {1'b1, tape_in, 1'b1, kd[4:0]};
reg port_fe_rd;
always @(posedge clk14)
port_fe_rd <= port_fe_cs && n_rd == 0;
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n) begin
beeper <= 0;
tape_out <= 0;
border <= 0;
end
else if (port_fe_cs && n_wr == 0) begin
beeper <= xd[4];
tape_out <= xd[3];
border <= xd[2:0];
end
end
/* PORT #7FFD */
wire port_7ffd_cs = n_m1 == 1 && n_iorq0 == 0 && xa[1] == 0 && xa[15] == 0 && xa[14] == 1;
reg [2:0] rambank;
reg rombank, vbank, lock_7ffd;
always @(posedge clk14 or negedge rst_n) begin
if (!rst_n) begin
rambank <= 0;
vbank <= 0;
rombank <= 0;
lock_7ffd <= 0;
end
else if (port_7ffd_cs && n_wr == 0 && lock_7ffd == 0) begin
rambank <= xd[2:0];
vbank <= xd[3];
rombank <= xd[4];
lock_7ffd <= xd[5];
end
end
assign clkcpu = turbo? clk_cnt[0] : clk_cnt[1];
/* AY */
@ -271,7 +222,7 @@ always @(posedge clkcpu or negedge rst_n) begin
ay_bdir <= xa[15] == 1 && xa[1] == 0 && n_m1 == 1 && n_iorq0 == 0 && n_wr == 0;
end
end
assign ay_clk = clk_cnt[2];
assign ay_clk = hc[1];
/* VIDEO */
@ -279,7 +230,7 @@ reg [2:0] chroma0;
chroma_gen chroma_gen1(
.cg_clock(clk16),
.cg_rgb({g,r,b}),
.cg_hsync(~hsync0),
.cg_hsync(hsync1),
.cg_enable(1'b1),
.cg_pnsel(1'b0),
.cg_out(chroma0)
@ -305,7 +256,7 @@ assign chroma[1] = chroma0[2]? chroma0[0] : 1'bz;
// 1 00 1 rom1
wire n_vcs_cpu = n_mreq | ~(a15 | a14);
assign n_vrd = ((n_vcs_cpu == 0 && n_rd == 0) || screen_read == 1)? 1'b0 : 1'b1 ;
assign n_vrd = ((n_vcs_cpu == 0 && n_rd == 0) || screen_read == 1)? 1'b0 : 1'b1;
assign n_vwr = ((n_vcs_cpu == 0 && n_wr == 0) && screen_read == 0)? 1'b0 : 1'b1;
always @(posedge clkcpu) begin
n_romcs <= n_mreq | a15 | a14;

View File

@ -41,7 +41,7 @@ set_global_assignment -name DEVICE "EPM7128SLC84-15"
set_global_assignment -name TOP_LEVEL_ENTITY zx_ula
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "9.0 SP2"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "08:15:12 APRIL 28, 2019"
set_global_assignment -name LAST_QUARTUS_VERSION "9.0 SP2"
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 15
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
@ -92,7 +92,7 @@ set_location_assignment PIN_49 -to vd[1]
set_location_assignment PIN_50 -to vd[0]
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE BALANCED
set_global_assignment -name FMAX_REQUIREMENT "14 MHz"
set_global_assignment -name FMAX_REQUIREMENT "14 MHz" -section_id clk14
set_location_assignment PIN_6 -to i
@ -130,6 +130,8 @@ set_global_assignment -name SAVE_DISK_SPACE OFF
set_global_assignment -name FIT_ONLY_ONE_ATTEMPT OFF
set_global_assignment -name SLOW_SLEW_RATE OFF
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output/
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS OFF
set_global_assignment -name SDC_FILE clocks.sdc
set_global_assignment -name VHDL_FILE chroma_gen16.vhd
set_global_assignment -name VERILOG_FILE top.v
set_global_assignment -name VERILOG_INCLUDE_FILE util.vh

BIN
out/zx_ula.pof vendored

Binary file not shown.