2022-12-05 16:55:23 +00:00
|
|
|
module ahb_vgasys_checker(
|
|
|
|
input wire HCLK,
|
|
|
|
input wire HRESETn,
|
|
|
|
input wire [31:0] HADDR,
|
|
|
|
input wire [31:0] HWDATA,
|
|
|
|
input wire HREADY,
|
|
|
|
input wire HWRITE,
|
|
|
|
input wire [1:0] HTRANS,
|
|
|
|
input wire HSEL,
|
|
|
|
input wire [31:0] HRDATA,
|
|
|
|
input wire HREADYOUT,
|
|
|
|
input wire HSYNC,
|
|
|
|
input wire VSYNC,
|
|
|
|
input wire [7:0] RGB,
|
|
|
|
output wire [7:0] checker_rgb_out
|
|
|
|
);
|
|
|
|
import ahb_vga_font_map::*;
|
|
|
|
// NOTE: Due to a BUG in the VGA module, the first 2 pixels for each row in the visible region is invalid, the actual image starts 2 cycles later
|
|
|
|
localparam text_region_x_min = 48 + 2;
|
|
|
|
localparam text_region_x_max = text_region_x_min + 240 - 2;
|
|
|
|
localparam text_region_y_min = 29;
|
|
|
|
localparam text_region_y_max = text_region_y_min + 480;
|
|
|
|
localparam character_width = 8;
|
|
|
|
localparam character_height = 16;
|
|
|
|
localparam characters_per_row = 240/character_width;
|
|
|
|
localparam characters_per_col = 480/character_height;
|
|
|
|
|
|
|
|
logic [31:0] counter;
|
|
|
|
logic countup;
|
|
|
|
int pixel_x;
|
|
|
|
int pixel_y;
|
|
|
|
//local coords within the visible text region
|
|
|
|
int frame_x;
|
|
|
|
int frame_y;
|
|
|
|
//local coords within the tile
|
|
|
|
logic [2:0] character_x;
|
|
|
|
logic [3:0] character_y;
|
|
|
|
|
|
|
|
logic [7:0] checker_rgb;
|
|
|
|
logic [7:0] character_buffer[characters_per_row*characters_per_col];
|
|
|
|
string console_text_reg;
|
|
|
|
|
|
|
|
int hcounter;
|
|
|
|
int vcounter;
|
|
|
|
|
|
|
|
|
|
|
|
function logic inTextRegion(int x, int y);
|
|
|
|
return (x >= text_region_x_min && x <= text_region_x_max) && (y >= text_region_y_min && y <= text_region_y_max);
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function int getStringIndex(int x, int y);
|
|
|
|
return (((y/character_height)*characters_per_row)+ (x/character_width));
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function logic[7:0] getRGBvalue(logic[2:0] x, logic[3:0] y, int char_index);
|
|
|
|
return font_lookup({char_index, y})[7-x] ? 8'h1c : 8'h00;
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
always_ff @(posedge HCLK)
|
|
|
|
begin
|
|
|
|
if(!HRESETn || !VSYNC)
|
|
|
|
begin
|
2022-12-16 20:19:07 +00:00
|
|
|
pixel_x <= 0;
|
|
|
|
pixel_y <= 0;
|
2022-12-12 16:16:17 +00:00
|
|
|
if(!HRESETn)
|
|
|
|
console_text_reg <= "";
|
|
|
|
counter <= 0;
|
2022-12-16 20:19:07 +00:00
|
|
|
countup <= 0;
|
2022-12-05 16:55:23 +00:00
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
countup <= countup + 1;
|
2022-12-12 16:16:17 +00:00
|
|
|
if($past(HSEL && HREADY && HWRITE && (HADDR[23:0]== 12'h000000000000),1) && HREADYOUT)
|
|
|
|
begin
|
|
|
|
console_text_reg <= {console_text_reg,font_map[HWDATA]};
|
|
|
|
character_buffer[counter] <= HWDATA[7:0];
|
|
|
|
counter <= counter+1;
|
|
|
|
end
|
|
|
|
if($fell(vgaif.HSYNC))
|
|
|
|
begin
|
|
|
|
pixel_x <= 0;
|
|
|
|
pixel_y <= pixel_y + 1;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
if(vgaif.HSYNC)
|
|
|
|
if(countup)
|
|
|
|
begin
|
|
|
|
pixel_x <= pixel_x + 1;
|
|
|
|
end
|
|
|
|
end
|
2022-12-05 16:55:23 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always_ff @(posedge HCLK)
|
|
|
|
begin
|
|
|
|
if(!HRESETn)
|
|
|
|
begin
|
|
|
|
hcounter <= 0;
|
|
|
|
vcounter <= 0;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
if($fell(VSYNC))
|
|
|
|
vcounter <= 0;
|
|
|
|
else
|
|
|
|
if($fell(HSYNC))
|
|
|
|
vcounter <= vcounter + 1;
|
|
|
|
if($fell(HSYNC))
|
|
|
|
hcounter <= 0;
|
|
|
|
else
|
|
|
|
hcounter <= hcounter + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always_comb
|
|
|
|
begin
|
|
|
|
checker_rgb = 0;
|
|
|
|
frame_x = pixel_x - text_region_x_min;
|
|
|
|
frame_y = pixel_y - text_region_y_min;
|
|
|
|
character_x = frame_x % character_width;
|
|
|
|
character_y = frame_y % character_height;
|
|
|
|
if(inTextRegion(pixel_x,pixel_y))
|
|
|
|
begin
|
|
|
|
if(getStringIndex(frame_x,frame_y) < console_text_reg.len())
|
|
|
|
begin
|
|
|
|
checker_rgb = getRGBvalue(character_x,character_y,character_buffer[getStringIndex(frame_x,frame_y)]);
|
|
|
|
//$display("char: %s, x: 0x%0h, y: 0x%0h",console_text_reg.substr(getStringIndex(frame_x,frame_y),getStringIndex(frame_x,frame_y)), frame_x, frame_y);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assign checker_rgb_out = checker_rgb;
|
|
|
|
|
|
|
|
//assertions
|
|
|
|
assert_text_region: assert property
|
|
|
|
(
|
|
|
|
@(posedge HCLK) disable iff (!HRESETn)
|
|
|
|
(inTextRegion(pixel_x,pixel_y) && (frame_x > 1)) -> (checker_rgb == RGB)
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_vsync_pulse_timer: assert property
|
|
|
|
(
|
|
|
|
@(posedge HCLK) disable iff (!HRESETn)
|
|
|
|
$rose(VSYNC) -> (($past(vcounter,1) == 8'h1) || (vcounter == '0))
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_hsync_pulse_timer: assert property
|
|
|
|
(
|
|
|
|
@(posedge HCLK) disable iff (!HRESETn)
|
|
|
|
($rose(HSYNC) && !$rose(VSYNC) && VSYNC) -> ($past(hcounter,1)/2 == 8'd95)
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_line_timer: assert property
|
|
|
|
(
|
|
|
|
@(posedge HCLK) disable iff (!HRESETn)
|
|
|
|
($fell(HSYNC) && !$rose(VSYNC) && VSYNC) -> ($past(hcounter,1)/2 == 800)
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_frame_timer: assert property
|
|
|
|
(
|
|
|
|
@(posedge HCLK) disable iff (!HRESETn)
|
|
|
|
$fell(VSYNC) -> (($past(vcounter,1) == (32'd480 + 32'd10 + 32'd2 + 32'd29)) || (vcounter == '0))
|
|
|
|
);
|
|
|
|
|
|
|
|
endmodule
|