module bitplane_to_raster (
// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,
// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out
);
// parameters
parameter PIPE_DELAY = 3; // minimum value of 2
// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;
// *****************************************************************************
// * *
// * DELAY PIPES *
// * *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_ram_h_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];
dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];
dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte
dly_ram_h_byte[0] <= ram_byte_h;
dly_ram_h_byte[9:1] <= dly_ram_h_byte[8:0];
pixel_out_h <= dly_ram_h_byte[PIPE_DELAY-1];
dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];
end // pc_ena
end // always@clk
// *****************************************************************************
// *****************************************************************************
// * *
// * RASTER GENERATION *
// * *
// *****************************************************************************
// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 = 2 colour mode - 8 pixels per byte in GPU RAM
// 01 = 4 colour mode - 4 pixels -----"------"------
// 10 = 16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------
always @ (posedge clk) begin
if (pc_ena[3:0] == 0) begin
if (~two_byte_mode) begin // 8-bit mode
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
if (ram_byte[(~x_out[2:0])] == 1'b1) begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];
end
else begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];
end
end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6], pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
pixel_out[7:2] <= 6'b000000;
case (x_out[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte[1:0];
end
endcase
end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color. EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
pixel_out[7:4] <= 4'b0000;
if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];
end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color. EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially
mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode
pixel_out <= ram_byte;
end
endcase
end // 8-bit mode
else begin // 16-bit mode
case (colour_mode_in[0])
1'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
if (ram_byte[(x_out[2:0])] == 1'b1) begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= ram_byte_h[7:4];
end
else begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= ram_byte_h[3:0];
end
end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output
mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode
pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;
end
endcase
end // 16-bit mode
end // if (pc_ena[3:0] == 0)
end // always@clk
endmodule
Oh right - I'm not used to there not being loads of things wrong with what I've written! I thought there must be something more...
Updated code below. I'm just trying to work out how to connect the bitplane_to_raster module up in the design schematic..
I'm either going to have to make design symbols for gpu_dual_port_ram_INTEL and/or multiport_gpu_ram, or do what we did in vid_osd_generator and instantiate those modules in the bitplane_to_raster code?Code: [Select]module bitplane_to_raster (
// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,
// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out
);
// parameters
parameter PIPE_DELAY = 3; // minimum value of 2
// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;
// *****************************************************************************
// * *
// * DELAY PIPES *
// * *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_ram_h_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];
dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];
dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte
dly_ram_h_byte[0] <= ram_byte_h;
dly_ram_h_byte[9:1] <= dly_ram_h_byte[8:0];
pixel_out_h <= dly_ram_h_byte[PIPE_DELAY-1];
dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];
end // pc_ena
end // always@clk
// *****************************************************************************
// *****************************************************************************
// * *
// * RASTER GENERATION *
// * *
// *****************************************************************************
// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 = 2 colour mode - 8 pixels per byte in GPU RAM
// 01 = 4 colour mode - 4 pixels -----"------"------
// 10 = 16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------
always @ (posedge clk) begin
if (pc_ena[3:0] == 0) begin
if (~two_byte_mode) begin // 8-bit mode
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
if (ram_byte[(~x_out[2:0])] == 1'b1) begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];
end
else begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];
end
end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6], pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
pixel_out[7:2] <= 6'b000000;
case (x_out[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte[1:0];
end
endcase
end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color. EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
pixel_out[7:4] <= 4'b0000;
if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];
end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color. EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially
mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode
pixel_out <= ram_byte;
end
endcase
end // 8-bit mode
else begin // 16-bit mode
case (colour_mode_in[0])
1'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
if (ram_byte[(x_out[2:0])] == 1'b1) begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= ram_byte_h[7:4];
end
else begin
pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= ram_byte_h[3:0];
end
end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output
mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode
pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;
end
endcase
end // 16-bit mode
end // if (pc_ena[3:0] == 0)
end // always@clk
endmodule
else begin // 16-bit mode
.............
if (ram_byte[(x_out[2:0])] == 1'b1) begin
Fix the multiple bugs in this part:Code: [Select]else begin // 16-bit mode
.............
if (ram_byte[(x_out[2:0])] == 1'b1) begin
The rest should follow #1.
Also, why did you :
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
and in 16 bit color mode:
1'h1 : begin // 16-bit (true colour)
Why not use 2'h3.
and change your 'case (colour_mode_in[0])' to the normal 'case (colour_mode_in)'?
else begin // 16-bit mode
case (colour_mode_in)
2'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.
mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode
if (ram_byte[(x_out[2:0])] == 1'b1) begin
pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;
end
else begin
pixel_out <= ram_byte;
pixel_out_h <= bg_colour;
end
end
2'h3 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output
mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode
pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;
end
endcase
end // 16-bit mode
// The resulting 2-bit font image at x is assigned to the OSD[1:0] output
// Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image = char_line[(~dly6_disp_x[2:0])];
Your fine, place it inside the OSD generator in place of the :Code: [Select]// The resulting 2-bit font image at x is assigned to the OSD[1:0] output
// Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image = char_line[(~dly6_disp_x[2:0])];
Note that you will need to make the new 'osd_image' output into a pixel_out and pixel_out_h ports. Call them pixel_out_top, pixel_out_top_h, and the wire 'pixel_out_top_16bit'
These 3 outputs will leave the vid_osd_generator. For now, set single byte test mode and wire the bg_color to a spare GPU_HW_REGS.
For now, wile the 8 bits into some of the RGBs wires to the stencil, maybe 'OR' in a few rast_HV triggers for testing, like only 2 or 4 of them.
My next message will contain the palette module which goes in between the vid_osd_generator module and the vid_out_stencil module.
Now for the palette memory. You will have 2 palettes.
Your fine, place it inside the OSD generator in place of the :Code: [Select]// The resulting 2-bit font image at x is assigned to the OSD[1:0] output
// Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image = char_line[(~dly6_disp_x[2:0])];
Note that you will need to make the new 'osd_image' output into a pixel_out and pixel_out_h ports. Call them pixel_out_top, pixel_out_top_h, and the wire 'pixel_out_top_16bit'
These 3 outputs will leave the vid_osd_generator. For now, set single byte test mode and wire the bg_color to a spare GPU_HW_REGS.
For now, wile the 8 bits into some of the RGBs wires to the stencil, maybe 'OR' in a few rast_HV triggers for testing, like only 2 or 4 of them.
My next message will contain the palette module which goes in between the vid_osd_generator module and the vid_out_stencil module.
Right, back again - work's been keeping me busy - so, when you say 'place it inside the OSD generator', can you be just a little more specific? Are you telling me to cut 'n' paste the code from bitplane_to_raster.v into vid_osd_generator.v in place of the osd_image assignment and work the new I/Os into the existing ones, or instantiate it (if that's even the right terminology?) in the same way that vid_osd_generator creates the multiport_gpu_ram instance?
Sorry about the basic question(s), but remember; a few weeks ago I knew the square root of nothing about FPGAs and Verilog...
Now for the palette memory. You will have 2 palettes.
Will these palette memories be easily accessible by the host system? I guess I'll just change the z80_bridge module to redirect reads/writes above address 16384 to the palette memory (or sprite memory or whatever else we add in)?
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE: For testing, GPU_HW_Control_regs [10] sets bg_colour
// * [11] sets two_byte_mode
// * [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(
.clk(clk),
.pc_ena_in(pc_ena[3:0]),
// inputs
.ram_byte_in( [7:0]),
.ram_byte_h( [7:0]),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( [1:0] GPU_HW_Control_regs[12] ),
.two_byte_mode( [0] GPU_HW_Control_regs[11] ),
// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out( [9:0]),
.colour_mode_out( [1:0])
);
module vid_osd_generator (
// inputs
input clk,
input [3:0] pc_ena,
input hde_in,
input vde_in,
input hs_in,
input vs_in,
input wire host_clk,
input wire host_wr_ena,
input wire [19:0] host_addr,
input wire [7:0] host_wr_data,
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],
input wire [47:0] HV_triggers_in,
// outputs
output reg osd_ena_out,
//output wire osd_image,
output reg pixel_out_top_16bit, // <--- new
output reg [7:0] pixel_out_top, // <--- new
output reg [7:0] pixel_out_top_h, // <--- new
output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,
output wire [7:0] host_rd_data,
output reg [47:0] HV_triggers_out
);
// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram. Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memory. Only 2 bits are used of the wr_data[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them
reg [9:0] disp_x,dly1_disp_x,dly2_disp_x,dly3_disp_x,dly4_disp_x,dly5_disp_x,dly6_disp_x,dly7_disp_x,dly8_disp_x;
reg [8:0] disp_y,dly1_disp_y,dly2_disp_y,dly3_disp_y,dly4_disp_y;
reg dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena,dly5_dena,dly6_dena;
reg [7:0] dly1_letter, dly2_letter, dly3_letter, dly4_letter;
reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;
reg [47:0] HV_pipe[9:0];
parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs. Only use 2 through 9.
parameter FONT_8x16 = 0; // 0 = 8 pixel tall font, 1 = 16 pixel tall font.
parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view
wire [12:0] font_pos;
wire [10:0] disp_pos;
wire [19:0] read_text_adr;
wire [19:0] read_font_adr;
wire [7:0] letter;
wire [7:0] char_line;
// ****************************************************************************************************************************
// *
// * create a multiport GPU RAM handler instance
// *
// ****************************************************************************************************************************
multiport_gpu_ram gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena[3:0]),
.addr_in_0(read_text_adr[19:0]),
.addr_in_1(read_font_adr[19:0]),
.addr_in_2(20'b0),
.addr_in_3(20'b0),
.addr_in_4(20'b0),
.cmd_in_0(16'b0),
.cmd_in_1(16'b0),
.cmd_in_2(16'b0),
.cmd_in_3(16'b0),
.cmd_in_4(16'b0),
.pc_ena_out(),
.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),
.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),
.data_out_0(letter[7:0]),
.data_out_1(char_line[7:0]),
.data_out_2(),
.data_out_3(),
.data_out_4(),
.clk_b(host_clk), // Host (Z80) clock input
.write_ena_b(host_wr_ena), // Host (Z80) clock enable
.addr_host_in(host_addr[19:0]),
.data_host_in(host_wr_data[7:0]),
.data_host_out(host_rd_data[7:0])
);
defparam gpu_RAM.ADDR_SIZE = 14, // pass ADDR_SIZE into the gpu_RAM instance
gpu_RAM.PIXEL_PIPE = 3; // set the length of the pixel pipe to offset multi-read port sequencing
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE: For testing, GPU_HW_Control_regs [10] sets bg_colour
// * [11] sets two_byte_mode
// * [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(
.clk(clk),
.pc_ena_in(pc_ena[3:0]),
// inputs
.ram_byte_in( [7:0]),
.ram_byte_h( [7:0]),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( [1:0] GPU_HW_Control_regs[12] ),
.two_byte_mode( [0] GPU_HW_Control_regs[11] ),
// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out( [9:0]),
.colour_mode_out( [1:0])
);
// The disp_x is the X coordinate counter. It runs from 0 to 512 and stops there
// The disp_y is the Y coordinate counter. It runs from 0 to 256 and stops there
// Get the character at the current x, y position
assign disp_pos[5:0] = disp_x[8:3] ; // The disp_pos[5:0] is the lower address for the 64 characters for the ascii text.
assign disp_pos[10:6] = disp_y[7+FONT_8x16:3+FONT_8x16] ; // the disp_pos[10:6] is the upper address for the 32 lines of text
// The result from the ascii memory component 'altsyncram_component_osd_mem' is called letter[7:0]
// Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.
// Now, font_pos[12:0] is the read address for the memory block containing the character specified in letter[]
assign font_pos[10+FONT_8x16:3+FONT_8x16] = letter[7:0] ; // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2+FONT_8x16:0] = dly3_disp_y[2+FONT_8x16:0] ; // select the font x coordinate with a 2 pixel clock DELAYED disp_x address. [3:1] is used so that every 2 x lines are repeats
// The resulting 2-bit font image at x is assigned to the OSD[1:0] output
// Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
//assign osd_image = char_line[(~dly6_disp_x[2:0])]; <--- edited out - replaced by bitplane_to_raster instance
assign read_text_adr[10:0] = disp_pos[10:0];
assign read_text_adr[19:11] = 9'h2; // my mistake, I has 1bit instead of 10bits
assign read_font_adr[10+FONT_8x16:0] = font_pos[10+FONT_8x16:0];
assign read_font_adr[19:11+FONT_8x16] = 0; // my mistake, I has 1bit instead of 10bits
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
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];
HV_pipe[0] <= HV_triggers_in;
HV_pipe[9:1] <= HV_pipe[8:0];
HV_triggers_out <= HV_pipe[PIPE_DELAY-1];
// **********************************************************************************************
// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates, I'm using an extra most
// significant bit in the counters to determine if the OSD ena flag should be on or off.
if (disp_x[9] || disp_y[8])
dena <= 0; // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else
dena <= 1; // otherwise, turn on the OSD output enable flag
if (~vde_in)
disp_y[8:0] <= 9'b111111111; // preset the disp_y counter to max while the vertical display is disabled
else if (hde_in && ~hde_pipe[0])
begin // isolate a single event at the begining of the active display area
disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter
if (!disp_y[8] | (disp_y[8:7] == 2'b11))
disp_y <= disp_y + 1'b1; // only increment the disp_y counter if it hasn't reached it's end
end
else if (!disp_x[9])
disp_x <= disp_x + 1'b1; // keep on addind to the disp_x counter until it reaches it's end.
// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;
dly3_disp_x <= dly2_disp_x;
dly4_disp_x <= dly3_disp_x;
dly5_disp_x <= dly4_disp_x;
dly6_disp_x <= dly5_disp_x;
dly7_disp_x <= dly6_disp_x;
dly8_disp_x <= dly7_disp_x;
dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;
dly3_disp_y <= dly2_disp_y;
dly4_disp_y <= dly3_disp_y;
dly1_letter <= letter;
dly2_letter <= dly1_letter;
dly3_letter <= dly2_letter;
dly4_letter <= dly3_letter;
dly1_dena <= dena;
dly2_dena <= dly1_dena;
dly3_dena <= dly2_dena;
dly4_dena <= dly3_dena;
dly5_dena <= dly4_dena;
dly6_dena <= dly5_dena;
// **********************************************************************************************
osd_ena_out <= dly4_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories
end // ena
end // always@clk
endmodule
Yes, for now we are not touching the dly_x_out of the new module.
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE: For testing, GPU_HW_Control_regs [10] sets bg_colour
// * [11] sets two_byte_mode
// * [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(
.clk(clk),
.pc_ena_in(pc_ena[3:0]),
// inputs
.ram_byte_in(char_line),
.ram_byte_h(8'b00000000),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][1:0] ),
.two_byte_mode( GPU_HW_Control_regs[11][0] ),
// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out(), // disconnected for moment
.colour_mode_out() // disconnected for moment
);
Get rid of the doctored color_sel.
Yes, for now we are not touching the dly_x_out of the new module.
Hmm... okay, here's where I am with the internal connections:Code: [Select]// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE: For testing, GPU_HW_Control_regs [10] sets bg_colour
// * [11] sets two_byte_mode
// * [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(
.clk(clk),
.pc_ena_in(pc_ena[3:0]),
// inputs
.ram_byte_in(char_line),
.ram_byte_h(8'b00000000),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][1:0] ),
.two_byte_mode( GPU_HW_Control_regs[11][0] ),
// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out(), // disconnected for moment
.colour_mode_out() // disconnected for moment
);Get rid of the doctored color_sel.
And replace it with...? I'm a little lost as to what we do with the 8-bit (and potentially 16-bit) output from vid_osd_generator now. The stencil doesn't have an 8-bit wide input - even color_sel doesn't - speaking of which, you want me to get rid of that completely?
Just tie the upper bits of '.pixel_out( pixel_out_top ),' to R,G,B.
We don't need snow or color settings from the debugger.
Shouldn't you be using 'dly6_disp_x'. Remember, since the first 'disp_x' has been used, there have been 6 pixel clock cycles until the '.ram_byte_in(char_line),' has a valid value.
Your 16 bit text mode doesn't look like the 8 bit text mode. Copy the 8 bit mode and replace the 'bg_color[]' with the 'ram_byte_h[]'.
----------------------------------------------
.pixel_out_ena( osd_ena_out ),
---------------------------------------------
Isn't osd_ena_out being set somewhere else.
Also, I don't see a disable mode in the current 6 modes. Also in a disable mode, you should also '0' the 2 data outputs.
I haven't a clue about the 5 pixel (ahem 4 pixel delay once you fix an obvious thing).
I turned back on the HV_triggers test lines so you may count the error pixels.
What in the world are all those delays for in the 'bitplane_to_raster' module?
Why would you want to add delay anywhere?
You are also missing a 'pixel_in_ena' and it's related function...
Your pixels are still off by 1 or 2 according to the image I see.
The original code has 0 delay on the bit selection. This new code has 1, so long as you remove all the internal delays. You need the other modules to take that into effect.
Also, the pixel enable input should also mute the output pixels when it low and it should be fed by the original 'osd_ena_out' wire.
You want a disabled mode, and an ability to mute out the non-display area of the OSD text window. So, both are needed.
You should have the original image, other than the text being blue, exactly if everything is done ok.
You want a disabled mode, and an ability to mute out the non-display area of the OSD text window. So, both are needed.
Okay, so what enables the disabled mode, if you'll excuse the oxymoron?
You want a disabled mode, and an ability to mute out the non-display area of the OSD text window. So, both are needed.
Okay, so what enables the disabled mode, if you'll excuse the oxymoron?
Well, you have 4 current modes, why not 7 modes and reserve a number for 'OFF'.
Arrrrrrggg, how did you do that? You found a different, yet perfect solution to a weird problem I never thought would end up like this....
Next, the 2 palettes.