How did you come to the conclusion that the 'addr_out_a' is a clock behind the ram 'data_out_a'?
Does this image not represent the GPU_INTEL memory:
(Attachment Link)
Count the number of clocks from address in to data out by counting the number of D-flipflops in the attached image...
How many do you count?
How many D-flipflops has the 'addr_out_a' gone through since the 'addr_a' input?
rd_addr_pipe_a <= addr_a;
addr_out_a <= rd_addr_pipe_a;
And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.
I'm going to need a bigger FPGA! It'll maybe stretch to doubling the multiport_gpu_ram module with it's ~33 KB of RAM, but certainly won't manage three or more such modules.
You are clear for a 15 port, 25Mhz x 16 bit read ram, or a read rate of 750 megabytes a second not counting the additional speed of the host port's 125 megabytes a second plus the palettes read speed.
You are clear for a 15 port, 25Mhz x 16 bit read ram, or a read rate of 750 megabytes a second not counting the additional speed of the host port's 125 megabytes a second plus the palettes read speed.
Well colour me impressed, then. I thought you meant there'd be three RAM modules (each 16 KB).
Ooh, latest project files attached.
The first 3 ports are the text and bottom display windows. The new 12 will be the 12 sprites, each again 1 window anywhere on the screen positioned by the HV_triggers, and any width and any height pointing anywhere in your bulk of GPU memory.
If you go to the 2 megabit lattice part, with it's 500MHz capable core ram, you will have room and cycle time for 30 read ports, leaving 27 sprites, or graphics windows overplayed on top of each other.
Now these window sprites can be larger than the display area too. Any X&Y size from memory meaning a 27 layer parallax scrolling game scenery is possible in full color. Talk about roasting the Amiga.
Each window layer can be at any resolution, any bitplane color depth, any zoom level, as long as they all share the same 256 color palette or, you set a layer to 65536 color mode where the palette will be bypassed.
module bitplane_to_raster (
// inputs
input wire clk,
input wire pixel_in_ena,
input wire [3:0] pc_ena,
input wire [15:0] ram_byte_in, // ****** changed to 16 bit width
input wire [7:0] ram_byte_h,
input wire [7:0] bg_colour,
input wire [9:0] x_in,
input wire [2: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 [2:0] colour_mode_out
);
// internal registers
//reg [7:0] colour_data;
// *****************************************************************************
// * *
// * PASS-THRUS *
// * *
// *****************************************************************************
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
x_out <= x_in;
//colour_data <= ram_byte_in; // in two-byte mode, colour_data should follow the ram_data byte
colour_mode_out <= colour_mode_in;
end // pc_ena
end // always@clk
// *****************************************************************************
// *****************************************************************************
// * *
// * RASTER GENERATION *
// * *
// *****************************************************************************
// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 = 2 colour mode - 8 pixels per byte in GPU RAM
// 001 = 4 colour mode - 4 pixels -----"------"------
// 010 = 16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF
always @ (posedge clk) begin
if (pc_ena[3:0] == 0) begin
pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output
if (~pixel_in_ena || colour_mode_in[2]) begin
// nothing to see here (disabled)
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
end
else 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_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= 4'b0000; // was: pixel_out[7:5] <= 3'b000;
pixel_out[3:0] <= bg_colour[7:4];
end
else begin
pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[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] <= bg_color[7:2];
case (x_in[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte_in[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte_in[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte_in[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte_in[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] <= bg_color[7:4];
if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[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_in[7:0];
end
endcase
end // 8-bit mode
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_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= bg_color[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];
end
else begin
pixel_out[7:4] <= bg_color[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];
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_in[7:0];
pixel_out_h <= ram_byte_h;
end
endcase
end // 16-bit mode
end // if (pc_ena[3:0] == 0)
end // always@clk
endmodule
An address generator resets to a base HW_REGS reg stored memory address once every v-sync.
Every (Y size) H-syncs, a second HW_REGS is added to that address generator base defining the horizontal size of the bitmap to be displayed.
Another HW reg store a pixel X size counter and Y size counter defining the width and height of the active window.
Another 2 store the X&Y beginning point of the window already setup with the HV_triggers.
2 more X&Y period size counters define the width and height of the pixels. (call this an X&Y zoom, or scale)
Another HW reg stores the bitplane color mode, background color and enable/disable.
This above address generator is identical for all graphics / sprite layers.
For the text mode, another HW_Reg stores the base address and X&Y pixel size of the font to be passed through the read port ram a second time from it's first address generator. Later in the Lattice part, with it's size, you may have the room for a text mode for every sprite layer making the Supernintendo's tile system look like a toy peanut.
An expansion patch to the bitplane to raster module...
...So now, if you define a sprite with 4 or 16 color pixels, you may choose the upper palette bits of that sprite's layer by setting the matching upper bits of it's bg_color. This way, each sprite can share or have it's own palette anywhere inside the 256 color palette as long as it isn't 256 color sprite where it obviously uses all 256 entries in the palette.
After the address generator, we will be modding the gpu_INTEL ram into a new wrapper module, running the the INTEL ram at 250MHz, making it's 2 ports into 4 ports at 125MHz. And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port. I hope you are up to the challenge. (We would need 1GHz 8 bit static ram to replicate this, not counting the palette memory which would double that as we might do the same 15 ports there for true multiple degrees of translucency between all layers instead of between 2 layers, then just transparent color 0 / vs non-transparent. Also in the lattice part, you will ran the ram at 500Mhz, in other words, you would need a 4GHz 8 bit static ram to replicate that display engine with it's 40 parallel read ports and 2x equivalent host_ ports.)
I hope I'm up to the challenge, as well! I might have to fold and ask for more breadcrumbs to get me through this more quickly, though. Can't believe I've wasted a day today hunting for (and thankfully fixing) two silly bugs.
I hope I'm up to the challenge, as well! I might have to fold and ask for more breadcrumbs to get me through this more quickly, though. Can't believe I've wasted a day today hunting for (and thankfully fixing) two silly bugs.Remember this one: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2782402/#msg2782402
Just scroll down the message and look for that big red '1' and you will see what took me hours to find...
In the new year, I wont have the same time as now, your gonna have to get used to finding bugs all on your own...
Next is the address generator/graphics instruction engine.
Here are the targeted controls/capable features: (We want to make 1 identical algorithm which will be used 4 times.)
1) Enable/disable. Requires 1 bit.
2) The base/beginning of a memory address which contains either the screen text data, font data, graphics data and sprite data. (This eats 20 bits since we can address 1 megabyte for this address)
3) Vertical memory increment size. When beginning a new line, this is the amount added every time to the base address. (16 bits is fair, maximum 64kb wide picture.)
4) Pixel type. 1bit=8 pixels wide per byte 2 colors per pixel,
2bit=4 pixels per byte 4 colors per pixel,
4bit=2 pixels per byte 16 colors,
8bit=1 pixel per byte, 256 colors,
16bit=2 bytes per pixel, 65k true-color
= 5 settings possible meaning requires 3 bits for this setting.
5) X scale. Counts the number of pixels wide each bitmap image pixel will occupy. 1 through 16 (4 bits)
6) Y scale. Counts the number of lines each bitmap image line will occupy. 1 through 16 (4 bits)
7) Sub-pixel starting X&Y coordinates. This setting vertically & horizontally shifts the image up and to the left by single pixels in text mode and 4/2/1 bit color modes. IE, smooth scrolling of text horizontally by up to 7/8th of 1 character, then you can change the base memory address by 1 character and reset this setting back to 0 allowing you to move the text pixel by pixel horizontally and vertically. The shift 16 pixels x by 16 pixels y , or 8 bits total.
8 ) Special control for font size. 8x8 pixel bitmap to 16x16 bitmap. 4 bit control.
9) Total number of video lines to render before loading a new set of the above controls. This will allow you to switch video modes mid screen, EG: have a window of 40 column text for half the screen, then switch to 80 column text for the bottom half.
Have I missed anything. The total here is around 14 control bytes, or, we will reserve 16 bytes per address generator and call it safe.
Extra Note: The horizontal and vertical windows and enables for the 16 sprites will be stored separately. 10bit X 10 bit Y.
Palettes also have a dedicated separate set of registers. A programmable interrupt generator based on a selected line of video will also be added for smooth animation apps.
Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte. Like 16bit color mode, pixel color bits, ect. (document these bit switches)
Step #1, minor touch up to the bitplane_to_raster.v module:
Add HW_REGS input to the bitplane_to_raster module.
Add a parameter which defines the base of the 3 control bytes:
The video mode byte, the bg_color byte and fg_color byte.
Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte. Like 16bit color mode, pixel color bits, ect. (document these bit switches)
Add a new input wire named 'enable_in'. When low, the pixel outputs will go to '0', identical to having the video mode set to 'off'.
Add a new output reg called 'enable_out'. Goes low when 'off' or 'enable_in' is low. Goes high when 'enable_in' is high and any selected valid video mode.
Start documenting the new controls. Also note that each display layer will have it's own bitplane_to_raster.v, so, this means 5 of them in you current design going up to 15 once we double the clock of your core memory, each with their own controls.
First part of the address generator, window coordinates, H&V size and H&V scale coming this afternoon.
module bitplane_to_raster (
// inputs
input wire clk,
input wire pixel_in_ena,
input wire two_byte_mode,
input wire enable_in,
input wire [3:0] pc_ena,
input wire [15:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_colour,
input wire [9:0] x_in,
//input wire [2:0] colour_mode_in,
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],
// outputs
output reg enable_out,
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 [2:0] colour_mode_out
);
parameter CTRL_BYTE_BASE = 8'h0; // defines the base address of the 3 control bytes (video_mode, bg_colour, fg_colour) in the HW_REGS
// *****************************************************************************
// video_mode byte - CTRL_BYTE_BASE + 0
//
// This HW_REG defines the video mode:
//
// 0000 - Off
// 0001 - 1 bit color
// 0010 - 2 bit color
// 0011 - 4 bit color
// 0100 - 8 bit color
// 0101 - 16 bit color
// 0110 - Special 2-byte text colour mode
// 0111 - ARGB4444
// 1000 - RGB565
// 1001 - 16 bit 565 thru
// 1010 - Mixed 16-bit 656 thru with last 256 colors assigned through the palette
// *****************************************************************************
parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view
// *****************************************************************************
// * *
// * PASS-THRUS *
// * *
// *****************************************************************************
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
x_out <= x_in;
//colour_mode_out <= colour_mode_in;
end // pc_ena
end // always@clk
// *****************************************************************************
// *****************************************************************************
// * *
// * RASTER GENERATION *
// * *
// *****************************************************************************
// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 = 2 colour mode - 8 pixels per byte in GPU RAM
// 001 = 4 colour mode - 4 pixels -----"------"------
// 010 = 16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF
always @ (posedge clk) begin
if (pc_ena[3:0] == 0) begin
pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output
enable_out <= enable_in;
if (~pixel_in_ena || ~enable_in) begin
// disable output as not in display area or enable_in is LOW
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
end
else begin
case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg
2'h0 : begin // off
// disable output as turned off
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
enable_out <= 1'b0; // set enable_out LOW
end
2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[7:4];
end
else begin
pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[3:0];
end
end
2'h2 : begin // 2-bit (4 colour) - 4 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out[7:2] <= bg_colour[7:2];
case (x_in[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte_in[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte_in[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte_in[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte_in[1:0];
end
endcase
end
2'h3 : begin // 4-bit (16 colour) - 2 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out[7:4] <= bg_colour[7:4];
if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];
end
2'h4 : begin // 8-bit (256 colour) - 1 pixel per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out <= ram_byte_in[7:0];
end
2'h5 : begin // 16-bit (true colour)
mode_16bit <= 1'b1; // set mode_16bit output to 16-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;
end
2'h6 : begin // special colour text mode
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];
end
else begin
pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];
end
end
endcase
end
end // if (pc_ena[3:0] == 0)
end // always@clk
endmodule
And now you know why within my RS232_Debugger HEX editor, you may click on the bits in the Binary view of the memory byte you are editing, and that bit will toggle allowing you to switch on and off multiple features controlled by different bits in a single byte.
Step #1, minor touch up to the bitplane_to_raster.v module:
Add HW_REGS input to the bitplane_to_raster module.
Add a parameter which defines the base of the 3 control bytes:
The video mode byte, the bg_color byte and fg_color byte.
Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte. Like 16bit color mode, pixel color bits, ect. (document these bit switches)
Add a new input wire named 'enable_in'. When low, the pixel outputs will go to '0', identical to having the video mode set to 'off'.
Add a new output reg called 'enable_out'. Goes low when 'off' or 'enable_in' is low. Goes high when 'enable_in' is high and any selected valid video mode.
Start documenting the new controls. Also note that each display layer will have it's own bitplane_to_raster.v, so, this means 5 of them in you current design going up to 15 once we double the clock of your core memory, each with their own controls.
First part of the address generator, window coordinates, H&V size and H&V scale coming this afternoon.
All done. Have hardwired enable_in HIGH in vid_osd_generator for testing.
I've removed colour_mode_in and colour_mode_out from the bitplane_to_raster module as they're not used now that the video_mode byte has taken over setting the mode. All working as expected so far.
bitplane_to_raster.v:Code: [Select]module bitplane_to_raster (
// inputs
input wire clk,
input wire pixel_in_ena,
input wire two_byte_mode,
input wire enable_in,
input wire [3:0] pc_ena,
input wire [15:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_colour,
input wire [9:0] x_in,
//input wire [2:0] colour_mode_in,
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],
// outputs
output reg enable_out,
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 [2:0] colour_mode_out
);
parameter CTRL_BYTE_BASE = 8'h0; // defines the base address of the 3 control bytes (video_mode, bg_colour, fg_colour) in the HW_REGS
// *****************************************************************************
// video_mode byte - CTRL_BYTE_BASE + 0
//
// This HW_REG defines the video mode:
//
// 0000 - Off
// 0001 - 1 bit color
// 0010 - 2 bit color
// 0011 - 4 bit color
// 0100 - 8 bit color
// 0101 - 16 bit color
// 0110 - Special 2-byte text colour mode
// 0111 - ARGB4444
// 1000 - RGB565
// 1001 - 16 bit 565 thru
// 1010 - Mixed 16-bit 656 thru with last 256 colors assigned through the palette
// *****************************************************************************
parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view
// *****************************************************************************
// * *
// * PASS-THRUS *
// * *
// *****************************************************************************
always @ ( posedge clk ) begin
if (pc_ena[3:0] == 0) begin
x_out <= x_in;
//colour_mode_out <= colour_mode_in;
end // pc_ena
end // always@clk
// *****************************************************************************
// *****************************************************************************
// * *
// * RASTER GENERATION *
// * *
// *****************************************************************************
// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 = 2 colour mode - 8 pixels per byte in GPU RAM
// 001 = 4 colour mode - 4 pixels -----"------"------
// 010 = 16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF
always @ (posedge clk) begin
if (pc_ena[3:0] == 0) begin
pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output
enable_out <= enable_in;
if (~pixel_in_ena || ~enable_in) begin
// disable output as not in display area or enable_in is LOW
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
end
else begin
case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg
2'h0 : begin // off
// disable output as turned off
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
enable_out <= 1'b0; // set enable_out LOW
end
2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[7:4];
end
else begin
pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[3:0];
end
end
2'h2 : begin // 2-bit (4 colour) - 4 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out[7:2] <= bg_colour[7:2];
case (x_in[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte_in[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte_in[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte_in[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte_in[1:0];
end
endcase
end
2'h3 : begin // 4-bit (16 colour) - 2 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out[7:4] <= bg_colour[7:4];
if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];
end
2'h4 : begin // 8-bit (256 colour) - 1 pixel per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out <= ram_byte_in[7:0];
end
2'h5 : begin // 16-bit (true colour)
mode_16bit <= 1'b1; // set mode_16bit output to 16-bit mode
enable_out <= 1'b1; // set enable_out HIGH
pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;
end
2'h6 : begin // special colour text mode
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];
end
else begin
pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];
end
end
endcase
end
end // if (pc_ena[3:0] == 0)
end // always@clk
endmodule
Also, we never got into this, but, are you using little or big endian for your data in the Z80? I don't know how the Z80 handles 16bit and 32bit math. We may want to get this fixed now...
Dont forget to remove the bg_color input and make a bg_color and fg_color wires which are assigned to the adjacent HW_Register for the control mode. Also, for now, make the default base address 16 decimal as we don't want to interfere with the first HV_Triggers.
2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte
mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out <= fg_colour;
end
else begin
pixel_out <= bg_colour;
end
end
Also, we never got into this, but, are you using little or big endian for your data in the Z80? I don't know how the Z80 handles 16bit and 32bit math. We may want to get this fixed now...
Little-endian. But it's what you do with it that counts.
EDIT: In terms of 16-bit and 32-bit math, it doesn't really do a lot - it is capable of doing limited 16-bit math with the instruction set, but mostly it's up to the user to write routines that do anything more complicated than addition or subtraction of 16-bit numbers.
As I'm sure you know, this is important as it defines when you write or copy all these settings, right now, the lower memory address holds the MSB of a 16 bit or 32 bit number. As you increase the memory address, you head toward the LSB. So, I assume we are keeping this setup?
IE, you wont be using any compilers/interpreters which store 16bit ints backwards making this graphics card incompatible?