Add VGA and GPIO checker

This commit is contained in:
Alden0012 2022-12-05 16:55:23 +00:00
parent f9bd753cde
commit f586cd95d9
5 changed files with 2728 additions and 1 deletions

View file

@ -0,0 +1,67 @@
module ahb_gpio_checker
( input wire HCLK
, input wire HRESETn
, input wire [31:0] HADDR
, input wire [ 1:0] HTRANS
, input wire [31:0] HWDATA
, input wire HWRITE
, input wire HSEL
, input wire HREADY
, input wire [16:0] GPIOIN
, input wire PARITYSEL
, input wire INJECT_FAULT
, input wire HREADYOUT
, input wire [31:0] HRDATA
, input wire [16:0] GPIOOUT
, input wire PARITYERR
);
logic gpio_cmd = HSEL && HREADY && HTRANS[1];
logic gpio_dir;
localparam [7:0] gpio_data_addr = 8'h00;
localparam [7:0] gpio_dir_addr = 8'h04;
// defined properties
property gpio_write;
@(posedge HCLK) disable iff (!HRESETn)
(HADDR[7:0] == gpio_data_addr) && gpio_cmd
##1
(gpio_dir=='1)
##1
(GPIOOUT[15:0] == $past(HWDATA,1));
endproperty
property gpio_read;
@(posedge HCLK) disable iff (!HRESETn)
(HADDR[7:0] == gpio_data_addr) && gpio_cmd
&& (gpio_dir=='0)
##1
((HRDATA[15:0]==$past(GPIOIN[15:0],1)) && HREADYOUT);
endproperty
always_ff @(posedge HCLK)
begin
if(!HRESETn)
begin
gpio_dir <= '0;
end
else
begin
if($past((gpio_cmd && (HADDR == gpio_dir_addr)),1))
begin
gpio_dir <= HWDATA;
end
end
end
// check behaviour
assert_parity: assert property
( @(posedge HCLK) disable iff (!HRESETn)
!PARITYERR
);
assert_gpio_write: assert property (gpio_write);
assert_gpio_read: assert property (gpio_read);
endmodule

View file

@ -18,6 +18,6 @@ module VGACOMPARATOR
&& HSYNC1 == HSYNC2
&& VSYNC1 == VSYNC2
&& RGB1 == RGB2
)
);
endmodule

View file

@ -0,0 +1,165 @@
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
pixel_x <= 0;
pixel_y <= 0;
console_text_reg <= "";
counter <= 0;
countup <= 0;
end
else
begin
countup <= countup + 1;
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
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

2316
tbench/ahb_vga_font_map.sv Normal file

File diff suppressed because it is too large Load diff

179
tbench/ahb_vga_tb.sv Normal file
View file

@ -0,0 +1,179 @@
// stub
interface ahb_vga_if;
typedef enum bit[1:0] {
IDLE = 2'b00,
BUSY = 2'b01,
NONSEQUENTIAL = 2'b10,
SEQUENTIAL = 2'b11
} htrans_types;
logic HCLK;
logic HRESETn;
logic [31:0] HADDR;
logic [ 1:0] HTRANS;
logic [31:0] HWDATA;
logic HWRITE;
logic HSEL;
logic HREADY;
logic HREADYOUT;
logic [31:0] HRDATA;
logic [7:0] RGB;
logic HSYNC;
logic VSYNC;
modport DUT
( input HCLK, HRESETn, HADDR, HTRANS, HWDATA, HWRITE, HSEL, HREADY,
output HREADYOUT, HRDATA, RGB, HSYNC, VSYNC
);
modport TB
( input HCLK, HREADYOUT, HRDATA, RGB, HSYNC, VSYNC,
output HRESETn, HREADY, HADDR, HTRANS, HWDATA, HWRITE, HSEL
);
endinterface
module ahb_vga_tb;
import ahb_vga_font_map::*;
localparam IMAGEADDR = 4'hA;
localparam CONSOLEADDR = 4'h0;
ahb_vga_if vgaif();
AHBVGA vga(
.HCLK(vgaif.HCLK),
.HRESETn(vgaif.HRESETn),
.HADDR(vgaif.HADDR),
.HWDATA(vgaif.HWDATA),
.HREADY(vgaif.HREADY),
.HWRITE(vgaif.HWRITE),
.HTRANS(vgaif.HTRANS),
.HSEL(vgaif.HSEL),
.HRDATA(vgaif.HRDATA),
.HREADYOUT(vgaif.HREADYOUT),
.HSYNC(vgaif.HSYNC),
.VSYNC(vgaif.VSYNC),
.RGB(vgaif.RGB)
);
logic [7:0] checker_rgb;
ahb_vgasys_checker vga_checker(
.HCLK(vgaif.HCLK),
.HRESETn(vgaif.HRESETn),
.HADDR(vgaif.HADDR),
.HWDATA(vgaif.HWDATA),
.HREADY(vgaif.HREADY),
.HWRITE(vgaif.HWRITE),
.HTRANS(vgaif.HTRANS),
.HSEL(vgaif.HSEL),
.HRDATA(vgaif.HRDATA),
.HREADYOUT(vgaif.HREADYOUT),
.HSYNC(vgaif.HSYNC),
.VSYNC(vgaif.VSYNC),
.RGB(vgaif.RGB),
.checker_rgb_out(checker_rgb)
);
logic display_enable;
task deassert_reset();
begin
vgaif.HRESETn = 0;
@(posedge vgaif.HCLK);
@(posedge vgaif.HCLK);
vgaif.HRESETn = 1;
end
endtask
initial begin
vgaif.HCLK = 0;
forever #20 vgaif.HCLK = ! vgaif.HCLK;
end
string line;
always @(posedge vgaif.HCLK) begin
if(display_enable)
if ($fell(vgaif.HSYNC)) begin
$display(line);
line = "";
end else if (vgaif.HSYNC)
if (checker_rgb == 8'd28)
line = {line, "#"};
else
line = {line, "."};
end
task setChar(input bit [7:0] c);
@(posedge vgaif.HCLK);
vgaif.HREADY = 1;
vgaif.HWRITE = 1;
vgaif.HTRANS = 2'b10;
vgaif.HSEL = 1;
vgaif.HADDR = 32'h50000000;
@(posedge(vgaif.HCLK));
vgaif.HWDATA = c;
vgaif.HWRITE = 0;
@(posedge (vgaif.HCLK && vgaif.HREADYOUT));
endtask
class vga_stimulus;
rand logic [31:0] HWDATA;
constraint c_hwdata
{0 <= HWDATA; HWDATA <= 8'h7f;}
endclass
vga_stimulus stimulus_vals;
covergroup cover_vga_chars;
cp_hwdata: coverpoint vgaif.HWDATA{
bins invalid = {[128:255]};
option.auto_bin_max = 128;
}
endgroup
integer char_index;
string test_value = "";
initial begin
cover_vga_chars covvgachars;
covvgachars = new();
stimulus_vals = new();
deassert_reset();
display_enable = 0;
@(posedge vgaif.VSYNC);
display_enable = 1;
$display(test_value);
for(char_index = 0; char_index < 16; char_index++)
begin
assert (stimulus_vals.randomize) else $fatal;
setChar(stimulus_vals.HWDATA);
test_value = {test_value, font_map[stimulus_vals.HWDATA]};
end
setChar(8'h08);
// setChar(8'h54);
// setChar(8'h45);
// setChar(8'h53);
// setChar(8'h54);
// setChar(8'h21);
// setChar(8'h00);
vgaif.HREADY = '0;
vgaif.HWRITE = '0;
vgaif.HTRANS = '0;
vgaif.HSEL = '0;
vgaif.HADDR = '0;
vgaif.HWDATA = '0;
@(posedge vgaif.VSYNC);
$display(test_value);
$stop;
end
logic rgb_active;
assign rgb_active = (vgaif.RGB==8'h1c);
logic checker_rgb_active;
assign checker_rgb_active = (checker_rgb==8'h1c);
endmodule