1
0
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:
Eugene Lozovoy
2022-07-09 21:38:12 +03:00
parent eb176e4c78
commit c3c105980e
5 changed files with 101 additions and 78 deletions

View File

@ -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

View File

@ -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:*}]

View File

@ -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 */

View File

@ -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

View File

@ -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