mirror of
https://github.com/UzixLS/zx-sizif-128.git
synced 2025-07-18 23:01:28 +03:00
cpld: refactor video color signal generation
assume 28.375MHz Y2 by default
This commit is contained in:
@ -1,14 +1,18 @@
|
|||||||
// Based on Joerg Wolfram's code //
|
// Based on Joerg Wolfram's code //
|
||||||
|
|
||||||
module chroma_gen #(
|
module chroma_gen #(
|
||||||
parameter CLK_FREQ
|
parameter CLK_FREQ = 16_000_000
|
||||||
) (
|
) (
|
||||||
input cg_clock, // input clock
|
input clk, // input clock
|
||||||
input cg_enable, // colour enable
|
input en, // colour enable
|
||||||
input cg_hsync, // hor. sync
|
input hsync, // hor. sync
|
||||||
input cg_pnsel, // system (pal/ntsc)
|
input ntsc, // system (pal/ntsc)
|
||||||
input [2:0] cg_rgb, // rgb input
|
input r, // rgbi input
|
||||||
output reg [2:0] cg_out // chroma out
|
input g,
|
||||||
|
input b,
|
||||||
|
input i,
|
||||||
|
output reg out_carrier, // chroma out
|
||||||
|
output reg [1:0] out
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam CARRIER_WIDTH =
|
localparam CARRIER_WIDTH =
|
||||||
@ -60,89 +64,103 @@ localparam NTSC_CARRIER =
|
|||||||
// localparam PAL_CARRIER = 64'd17_734_475 * (1<<(CARRIER_WIDTH-1)) / CLK_FREQ;
|
// localparam PAL_CARRIER = 64'd17_734_475 * (1<<(CARRIER_WIDTH-1)) / CLK_FREQ;
|
||||||
// localparam NTSC_CARRIER = 64'd14_318_180 * (1<<(CARRIER_WIDTH-1)) / CLK_FREQ;
|
// localparam NTSC_CARRIER = 64'd14_318_180 * (1<<(CARRIER_WIDTH-1)) / CLK_FREQ;
|
||||||
|
|
||||||
reg [CARRIER_WIDTH:0] carrier;
|
|
||||||
wire [31:0] carrier_next;
|
|
||||||
reg [3:0] burst_cnt;
|
|
||||||
wire burst;
|
|
||||||
reg oddeven;
|
|
||||||
reg [3:0] phase;
|
|
||||||
reg [3:0] scarrier;
|
|
||||||
wire cenable;
|
|
||||||
|
|
||||||
|
|
||||||
// DDS for PAL-carrier
|
// DDS for PAL-carrier
|
||||||
assign carrier_next = (cg_pnsel == 1'b0)?
|
reg [CARRIER_WIDTH:0] carrier;
|
||||||
|
wire [31:0] carrier_next = (!ntsc)?
|
||||||
(carrier + PAL_CARRIER) :
|
(carrier + PAL_CARRIER) :
|
||||||
(carrier + NTSC_CARRIER) ;
|
(carrier + NTSC_CARRIER) ;
|
||||||
|
always @(posedge clk) begin
|
||||||
always @(posedge cg_clock) begin
|
|
||||||
carrier <= carrier_next[CARRIER_WIDTH:0];
|
carrier <= carrier_next[CARRIER_WIDTH:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// burst generator
|
// burst generator
|
||||||
always @(posedge carrier[CARRIER_WIDTH] or negedge cg_hsync) begin
|
reg [3:0] burst_cnt;
|
||||||
if (cg_hsync == 1'b0)
|
always @(posedge carrier[CARRIER_WIDTH] or negedge hsync) begin
|
||||||
|
if (hsync == 1'b0)
|
||||||
burst_cnt <= 4'b0100;
|
burst_cnt <= 4'b0100;
|
||||||
else if (burst_cnt != 4'b0000)
|
else if (burst_cnt != 4'b0000)
|
||||||
burst_cnt <= burst_cnt + 1'b1;
|
burst_cnt <= burst_cnt + 1'b1;
|
||||||
end
|
end
|
||||||
assign burst = burst_cnt[3];
|
wire burst = burst_cnt[3];
|
||||||
|
|
||||||
|
|
||||||
// odd/even line
|
// odd/even line
|
||||||
always @(posedge cg_hsync) begin
|
reg oddeven;
|
||||||
if (cg_pnsel == 1'b0)
|
always @(posedge hsync) begin
|
||||||
|
if (!ntsc)
|
||||||
oddeven <= ~oddeven;
|
oddeven <= ~oddeven;
|
||||||
else
|
else
|
||||||
oddeven <= 1'b0;
|
oddeven <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
// carrier phase
|
// carrier phase
|
||||||
|
reg [3:0] phase;
|
||||||
always @* begin
|
always @* begin
|
||||||
if (burst == 1'b1) begin
|
if (burst == 1'b1) begin
|
||||||
if ((oddeven == 1'b0) && (cg_pnsel == 1'b0))
|
if ((oddeven == 1'b0) && (!ntsc))
|
||||||
phase <= 4'b0110; // burst phase 135 deg
|
phase <= 4'h6; // burst phase 135 deg
|
||||||
else
|
else
|
||||||
phase <= 4'b1010; // burst phase -135 deg
|
phase <= 4'hA; // burst phase -135 deg
|
||||||
end
|
end
|
||||||
else if (oddeven == 1'b0) begin
|
else if (oddeven == 1'b0) begin
|
||||||
case (cg_rgb)
|
case ({r,g,b})
|
||||||
3'b001: phase <= 4'b0000; // blue phase
|
3'b010: phase <= 4'hB; // green
|
||||||
3'b010: phase <= 4'b0101; // red phase
|
3'b011: phase <= 4'hD; // cyan
|
||||||
3'b011: phase <= 4'b0011; // magenta phase
|
3'b100: phase <= 4'h5; // red
|
||||||
3'b100: phase <= 4'b1011; // green phase
|
3'b101: phase <= 4'h3; // magenta
|
||||||
3'b101: phase <= 4'b1101; // cyan phase
|
3'b110: phase <= 4'h7; // yellow
|
||||||
3'b110: phase <= 4'b0111; // yellow phase
|
default: phase <= 4'hF; // blue
|
||||||
default: phase <= 4'b0000; // dummy function
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
case (cg_rgb)
|
case ({r,g,b})
|
||||||
3'b001: phase <= 4'b0000; // blue phase
|
3'b010: phase <= 4'h5; // green
|
||||||
3'b010: phase <= 4'b1011; // red phase
|
3'b011: phase <= 4'h3; // cyan
|
||||||
3'b011: phase <= 4'b1101; // magenta phase
|
3'b100: phase <= 4'hB; // red
|
||||||
3'b100: phase <= 4'b0101; // green phase
|
3'b101: phase <= 4'hD; // magenta
|
||||||
3'b101: phase <= 4'b0011; // cyan phase
|
3'b110: phase <= 4'h9; // yellow
|
||||||
3'b110: phase <= 4'b1001; // yellow phase
|
default: phase <= 4'h1; // blue
|
||||||
default: phase <= 4'b0000; // dummy function
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// carrier amplitude
|
||||||
|
reg [1:0] amplitude;
|
||||||
|
always @* begin
|
||||||
|
if (burst == 1'b1)
|
||||||
|
amplitude <= 2'b01;
|
||||||
|
else case ({i,r,g,b})
|
||||||
|
4'b0001: amplitude <= 2'b10;
|
||||||
|
4'b0010: amplitude <= 2'b10;
|
||||||
|
4'b0011: amplitude <= 2'b10;
|
||||||
|
4'b0100: amplitude <= 2'b10;
|
||||||
|
4'b0101: amplitude <= 2'b10;
|
||||||
|
4'b0110: amplitude <= 2'b10;
|
||||||
|
4'b1001: amplitude <= 2'b11;
|
||||||
|
4'b1010: amplitude <= 2'b11;
|
||||||
|
4'b1011: amplitude <= 2'b11;
|
||||||
|
4'b1100: amplitude <= 2'b11;
|
||||||
|
4'b1101: amplitude <= 2'b11;
|
||||||
|
4'b1110: amplitude <= 2'b11;
|
||||||
|
default: amplitude <= 2'b00;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// modulated carrier
|
// modulated carrier
|
||||||
|
reg [3:0] scarrier;
|
||||||
always @*
|
always @*
|
||||||
scarrier <= carrier[CARRIER_WIDTH:CARRIER_WIDTH-3] + phase;
|
scarrier <= carrier[CARRIER_WIDTH:CARRIER_WIDTH-3] + phase;
|
||||||
|
|
||||||
// colour enable
|
|
||||||
assign cenable =
|
|
||||||
cg_enable == 1'b1 &&
|
|
||||||
cg_rgb != 3'b000 &&
|
|
||||||
cg_rgb != 3'b111;
|
|
||||||
|
|
||||||
// chroma signal
|
// chroma signal
|
||||||
always @(posedge cg_clock) begin
|
always @(posedge clk) begin
|
||||||
cg_out[2] <= cenable;
|
out_carrier <= scarrier[3];
|
||||||
cg_out[1] <= burst;
|
out[1] <= en && amplitude[1];
|
||||||
cg_out[0] <= scarrier[3];
|
out[0] <= en && amplitude[0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
create_clock -period 14.4MHz -name {clk_14mhz} [get_ports {clk14}]
|
create_clock -period 14.4MHz -name {clk_14mhz} [get_ports {clk14}]
|
||||||
create_clock -period 16.1MHz -name {clk_16mhz} [get_ports {clk16}]
|
create_clock -period 32.1MHz -name {clk_pal} [get_ports {clkpal}]
|
||||||
|
|
||||||
# clkcpu 3.5
|
|
||||||
create_generated_clock -name {clkcpu} -divide_by 4 -source [get_ports {clk14}] [get_registers {hc0[1]}]
|
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}]
|
create_generated_clock -name {n_int} -divide_by 64 -source [get_ports {clk14}] [get_registers {n_int~reg0}]
|
||||||
|
create_generated_clock -name {hsync1} -divide_by 64 -source [get_ports {clk14}] [get_registers {hsync1}]
|
||||||
|
create_generated_clock -name {chroma_carrier} -divide_by 6 -source [get_ports {clkpal}] [get_registers {chroma_gen:*|carrier[16]}]
|
||||||
|
|
||||||
# chroma carrier (4.43MHz)
|
# All these transitions happens when carrier is inactive, so no any glitches will be visible
|
||||||
create_generated_clock -name {chroma_carrier} -divide_by 3 -source [get_ports {clk16}] [get_registers {*:chroma_gen1|carrier[14]}]
|
set_false_path -from [get_registers {chroma_gen:*|burst_cnt[3]}] -to [get_registers {chroma_gen:*|out_carrier}]
|
||||||
|
set_false_path -from [get_registers {chroma_gen:*|oddeven}] -to [get_registers {chroma_gen:*|out_carrier}]
|
||||||
|
set_false_path -from [get_registers {hsync1}] -to [get_registers {chroma_gen:*|burst_cnt[*]}]
|
||||||
|
|
||||||
set_false_path -from [get_registers {r~reg0}] -to [get_clocks {clk_16mhz}]
|
set_false_path -from [get_registers {r~reg0}] -to [get_registers {chroma_gen:*}]
|
||||||
set_false_path -from [get_registers {g~reg0}] -to [get_clocks {clk_16mhz}]
|
set_false_path -from [get_registers {g~reg0}] -to [get_registers {chroma_gen:*}]
|
||||||
set_false_path -from [get_registers {b~reg0}] -to [get_clocks {clk_16mhz}]
|
set_false_path -from [get_registers {b~reg0}] -to [get_registers {chroma_gen:*}]
|
||||||
set_false_path -from [get_registers {hsync1}] -to [get_clocks {chroma_carrier}]
|
set_false_path -from [get_registers {i~reg0}] -to [get_registers {chroma_gen:*}]
|
||||||
|
29
cpld/top.v
29
cpld/top.v
@ -1,7 +1,7 @@
|
|||||||
module zx_ula(
|
module zx_ula(
|
||||||
input rst_n,
|
input rst_n,
|
||||||
input clk14,
|
input clk14,
|
||||||
input clk16,
|
input clkpal,
|
||||||
|
|
||||||
output clkcpu,
|
output clkcpu,
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ module zx_ula(
|
|||||||
output reg csync
|
output reg csync
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [15:0] xa = {a15, a14, va[13:2], a1, a0}; // a1-va[1] and a0-va[0] may be swapped if fitter is cranky
|
wire [15:0] xa = {a15, a14, va[13:2], va[1], va[0]}; // a1-va[1] and a0-va[0] may be swapped if fitter is cranky
|
||||||
wire [7:0] xd = vd;
|
wire [7:0] xd = vd;
|
||||||
|
|
||||||
reg screen_read;
|
reg screen_read;
|
||||||
@ -206,17 +206,22 @@ assign ay_clk = hc[1];
|
|||||||
|
|
||||||
|
|
||||||
/* VIDEO */
|
/* VIDEO */
|
||||||
reg [2:0] chroma0;
|
wire chroma_carrier;
|
||||||
chroma_gen #(.CLK_FREQ(16_000_000)) chroma_gen1(
|
wire [1:0] chroma0;
|
||||||
.cg_clock(clk16),
|
chroma_gen #(.CLK_FREQ(28_375_000)) chroma_gen1(
|
||||||
.cg_rgb({g,r,b}),
|
.clk(clkpal),
|
||||||
.cg_hsync(hsync1),
|
.hsync(hsync1),
|
||||||
.cg_enable(1'b1),
|
.en(1'b1),
|
||||||
.cg_pnsel(1'b0),
|
.ntsc(1'b0),
|
||||||
.cg_out(chroma0)
|
.r(r),
|
||||||
|
.g(g),
|
||||||
|
.b(b),
|
||||||
|
.i(i),
|
||||||
|
.out_carrier(chroma_carrier),
|
||||||
|
.out(chroma0)
|
||||||
);
|
);
|
||||||
assign chroma[0] = chroma0[1]? chroma0[0] : 1'bz;
|
assign chroma[0] = chroma0[0]? chroma_carrier : 1'bz;
|
||||||
assign chroma[1] = chroma0[2]? chroma0[0] : 1'bz;
|
assign chroma[1] = chroma0[1]? chroma_carrier : 1'bz;
|
||||||
|
|
||||||
|
|
||||||
/* MEMORY CONTROLLER */
|
/* MEMORY CONTROLLER */
|
||||||
|
@ -105,7 +105,7 @@ set_location_assignment PIN_16 -to a15
|
|||||||
set_global_assignment -name AUTO_RESOURCE_SHARING OFF
|
set_global_assignment -name AUTO_RESOURCE_SHARING OFF
|
||||||
set_global_assignment -name AUTO_LCELL_INSERTION OFF
|
set_global_assignment -name AUTO_LCELL_INSERTION OFF
|
||||||
set_location_assignment PIN_9 -to csync
|
set_location_assignment PIN_9 -to csync
|
||||||
set_location_assignment PIN_2 -to clk16
|
set_location_assignment PIN_2 -to clkpal
|
||||||
set_location_assignment PIN_11 -to chroma[1]
|
set_location_assignment PIN_11 -to chroma[1]
|
||||||
set_location_assignment PIN_12 -to chroma[0]
|
set_location_assignment PIN_12 -to chroma[0]
|
||||||
set_location_assignment PIN_33 -to kd[1]
|
set_location_assignment PIN_33 -to kd[1]
|
||||||
@ -118,8 +118,6 @@ set_location_assignment PIN_40 -to ay_bdir
|
|||||||
set_location_assignment PIN_41 -to ay_clk
|
set_location_assignment PIN_41 -to ay_clk
|
||||||
set_location_assignment PIN_79 -to tape_in
|
set_location_assignment PIN_79 -to tape_in
|
||||||
set_location_assignment PIN_80 -to ra14
|
set_location_assignment PIN_80 -to ra14
|
||||||
set_global_assignment -name FMAX_REQUIREMENT "16 MHz" -section_id clk16
|
|
||||||
set_instance_assignment -name CLOCK_SETTINGS clk16 -to clk16
|
|
||||||
set_global_assignment -name BASED_ON_CLOCK_SETTINGS clk14 -section_id clkcpu
|
set_global_assignment -name BASED_ON_CLOCK_SETTINGS clk14 -section_id clkcpu
|
||||||
set_global_assignment -name MULTIPLY_BASE_CLOCK_PERIOD_BY 2 -section_id clkcpu
|
set_global_assignment -name MULTIPLY_BASE_CLOCK_PERIOD_BY 2 -section_id clkcpu
|
||||||
set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF
|
set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF
|
||||||
|
@ -6,4 +6,5 @@ To improve RGBI colour balance use these values:
|
|||||||
2. R42 10k
|
2. R42 10k
|
||||||
3. R39 18k
|
3. R39 18k
|
||||||
4. R46 15k
|
4. R46 15k
|
||||||
5. R49 3.6k
|
5. R49 2.4k
|
||||||
|
6. R50 4.7k
|
||||||
|
Reference in New Issue
Block a user