Latest pixel_mixer.v:
module palette_mixer (
// inputs
input clk,
input vs_in,
input hs_in,
input hde_in,
input vde_in,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,
// outputs
output reg [3:0] pc_ena_out,
//
output reg [7:0] pixel_out_r,
output reg [7:0] pixel_out_g,
output reg [7:0] pixel_out_b,
//
output reg vs_out,
output reg hs_out,
output reg hde_out,
output reg vde_out,
// host port
input [9:0] host_addr_in,
input [7:0] host_data_in,
output reg [7:0] host_data_out
);
parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs. Only use 2 through 9.
wire pc_enable = (pc_ena_in[3:0]==0);
// **** TO DO:
wire host_wren_txt; // need to complete this so that they go high when
wire host_wren_gfx; // the palette is correctly addressed by the host
// ****
wire [15:0] txt_pixel_out;
wire [3:0] alpha_blend;
wire [7:0] text_r;
wire [7:0] text_g;
wire [7:0] text_b;
wire [15:0] gfx_pixel_out;
wire [7:0] graphics_r;
wire [7:0] graphics_g;
wire [7:0] graphics_b;
reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes
reg [7:0] pixel_r1, pixel_r2, pixel_g1, pixel_g2, pixel_b1, pixel_b2;
assign alpha_blend = txt_pixel_out[15:12];
assign text_r[7:4] = txt_pixel_out[11:8];
assign text_r[3:0] = txt_pixel_out[11:8];
assign text_g[7:4] = txt_pixel_out[7:4];
assign text_g[3:0] = txt_pixel_out[7:4];
assign text_b[7:4] = txt_pixel_out[3:0];
assign text_b[3:0] = txt_pixel_out[3:0];
assign graphics_r[7:3] = gfx_pixel_out[15:11];
assign graphics_r[2:0] = gfx_pixel_out[15:13];
assign graphics_g[7:2] = gfx_pixel_out[10:5];
assign graphics_g[1:0] = gfx_pixel_out[10:9];
assign graphics_b[7:3] = gfx_pixel_out[4:0];
assign graphics_b[2:0] = gfx_pixel_out[4:2];
// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(
// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(txt_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_txt),
// outputs
.pixel_out(txt_pixel_out),
.host_data_out(host_data_out)
);
defparam text_palette_RAM.INIT_PALETTE = "palette_4444.mif";
// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(
// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(gfx_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_gfx),
// outputs
.pixel_out(gfx_pixel_out),
.host_data_out(data_out_b)
);
defparam graphics_palette_RAM.INIT_PALETTE = "palette_565.mif";
// *********************************************************************
always @(posedge clk) begin
if (pc_ena_in[3:0] == 0) begin
hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];
vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];
hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];
vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];
// mix output rgb
pixel_r1 <= (text_r[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_r2 <= (graphics_r[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_r <= pixel_r1 + pixel_r2;
pixel_g1 <= (text_g[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_g2 <= (graphics_g[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_g <= pixel_g1 + pixel_g2;
pixel_b1 <= (text_b[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_b2 <= (graphics_b[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_b <= pixel_b1 + pixel_b2;
end
end
endmodule
Latest dual_port_palette_ram_INTEL.v:
module dual_port_palette_ram_text (
// inputs
input clock_a,
input clock_b,
input [7:0] pixel_addr_in, // address_a
input [8:0] host_address,
input [15:0] data_a,
input [7:0] host_data_in,
input enable_a,
input host_enable,
input wren_a,
input host_wren,
// outputs
output [15:0] pixel_out, // data_out_a
output [7:0] host_data_out
);
parameter INIT_PALETTE = "palette_565.mif";
// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (enable_a),
.clocken1 (host_enable),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (host_wren),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (host_address),
.data_a (data_a),
.data_b (host_data_in),
.q_a (pixel_out),
.q_b (host_data_out),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (1'b1),
.rden_b (1'b1)
);
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = INIT_PALETTE,
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";
// ****************************************************************************************************************************
endmodule
Need to sort the wr_en's for the graphics and text palette memory though.