vgafb: first attempt at shifter/masker acceleration functionality

This commit is contained in:
slederer 2026-01-26 02:03:28 +01:00
parent d17c4c41fd
commit 248c9ae919
3 changed files with 97 additions and 4 deletions

View file

@ -1,6 +1,9 @@
`timescale 1ns / 1ps
`default_nettype none
// enable shifter/masker registers
`define ENABLE_FB_ACCEL
// Project F: Display Timings
// (C)2019 Will Green, Open Source Hardware released under the MIT License
// Learn more at https://projectf.io
@ -126,6 +129,14 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
localparam REG_PAL_SLOT = 3; localparam REG_PAL_DATA = 4;
localparam REG_CTL = 5;
`ifdef ENABLE_FB_ACCEL
localparam REG_SHIFTER = 6;
localparam REG_SHIFTCOUNT = 7;
localparam REG_SHIFTERM = 9;
localparam REG_SHIFTERSP = 10;
localparam REG_MASKGEN = 11;
`endif
localparam COLOR_WIDTH = 12;
localparam PALETTE_WIDTH = 4;
@ -145,12 +156,30 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
wire pix_rd;
wire [VMEM_DATA_WIDTH-1:0] status;
`ifdef ENABLE_FB_ACCEL
reg [VMEM_DATA_WIDTH-1:0] acc_shifter_in;
reg [(VMEM_DATA_WIDTH*2)-1:0] acc_shifter_out;
reg [2:0] acc_shift_count;
reg acc_start_shift;
reg [VMEM_DATA_WIDTH-1:0] acc_mask_in;
wire [VMEM_DATA_WIDTH-1:0] acc_mask_out;
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_mask;
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_out_h = acc_shifter_out[(VMEM_DATA_WIDTH*2)-1:VMEM_DATA_WIDTH];
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_out_l = acc_shifter_out[VMEM_DATA_WIDTH-1:0];
`endif
assign vmem_rd_en = rd_en;
assign vmem_wr_en = (reg_sel == REG_VMEM) && wr_en;
assign rd_data = (reg_sel == REG_VMEM) ? vmem_rd_data :
(reg_sel == REG_RD_ADDR) ? cpu_rd_addr :
(reg_sel == REG_WR_ADDR) ? cpu_wr_addr :
(reg_sel == REG_CTL) ? status :
`ifdef ENABLE_FB_ACCEL
(reg_sel == REG_SHIFTER) ? acc_shifter_out_h:
(reg_sel == REG_SHIFTERM) ? acc_shifter_mask :
(reg_sel == REG_SHIFTERSP) ? acc_shifter_out_l :
(reg_sel == REG_MASKGEN) ? acc_mask_out :
`endif
32'hFFFFFFFF;
wire [VMEM_ADDR_WIDTH-1:0] cpu_addr = vmem_wr_en ? cpu_wr_addr : cpu_rd_addr;
@ -271,6 +300,71 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
if(rd_en && reg_sel == REG_VMEM) cpu_rd_addr <= cpu_rd_addr + 1; // auto-increment read addr on read
end
`ifdef ENABLE_FB_ACCEL
//
// shifter/masker registers
//
always @(posedge cpu_clk)
begin
if(wr_en && reg_sel == REG_SHIFTER)
acc_shifter_in <= { wr_data, {32{1'b0}}};
end
always @(posedge cpu_clk)
begin
if(wr_en && reg_sel == REG_SHIFTCOUNT)
begin
acc_shift_count <= wr_data[2:0];
acc_start_shift <= 1;
end
if(acc_start_shift)
acc_start_shift <= 0;
end
always @(posedge cpu_clk)
begin
if (acc_start_shift)
begin
acc_shifter_out <= {acc_shifter_in, {VMEM_DATA_WIDTH{1'b0}}} >> acc_shift_count;
end
end
// mask register
always @(posedge cpu_clk)
begin
if (wr_en && reg_sel == REG_MASKGEN)
begin
acc_mask_in <= wr_data;
end
end
assign acc_mask_out = {
{4{|{acc_mask_in[31:28]}}},
{4{|{acc_mask_in[27:24]}}},
{4{|{acc_mask_in[23:20]}}},
{4{|{acc_mask_in[19:16]}}},
{4{|{acc_mask_in[15:12]}}},
{4{|{acc_mask_in[11:8]}}},
{4{|{acc_mask_in[7:4]}}},
{4{|{acc_mask_in[3:0]}}}
};
assign acc_shifter_mask = {
{4{|{acc_shifter_out_h[31:28]}}},
{4{|{acc_shifter_out_h[27:24]}}},
{4{|{acc_shifter_out_h[23:20]}}},
{4{|{acc_shifter_out_h[19:16]}}},
{4{|{acc_shifter_out_h[15:12]}}},
{4{|{acc_shifter_out_h[11:8]}}},
{4{|{acc_shifter_out_h[7:4]}}},
{4{|{acc_shifter_out_h[3:0]}}}
};
`endif
//
// shifting pixels at pixel clock
//
always @(posedge pix_clk)
begin
if(scanline || shift_count == MAX_SHIFT_COUNT) // before start of a line