mirror of
https://github.com/supleed2/ELEC70056-HSV-CW2.git
synced 2024-12-22 13:45:49 +00:00
Add VGA and GPIO checker
This commit is contained in:
parent
f9bd753cde
commit
f586cd95d9
67
rtl/AHB_GPIO/ahb_gpio_checker.sv
Normal file
67
rtl/AHB_GPIO/ahb_gpio_checker.sv
Normal 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
|
|
@ -18,6 +18,6 @@ module VGACOMPARATOR
|
|||
&& HSYNC1 == HSYNC2
|
||||
&& VSYNC1 == VSYNC2
|
||||
&& RGB1 == RGB2
|
||||
)
|
||||
);
|
||||
|
||||
endmodule
|
165
rtl/AHB_VGA/ahb_vgasys_checker.sv
Normal file
165
rtl/AHB_VGA/ahb_vgasys_checker.sv
Normal 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
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
179
tbench/ahb_vga_tb.sv
Normal 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
|
Loading…
Reference in a new issue