Research-Stack/4-Infrastructure/hardware/highs_pivot_accelerator.v
Brandon Schneider e2f3a9e93b feat: HiGHS integration, scale space solver, adjugate matrix, FPGA voltage/BRAM modules
HiGHS Optimization:
- qubo_highs.py: QUBO→MIP reformulation via highspy (exact, not approximate)
- solve_route_lp: TSP/VRP assignment relaxation for RouteCost 39-node graph
- scale_space_solver.py: multi-scale optimization (coarse LP → fine MIP)
- Gaussian kernels in Q16_16, voltage↔scale mapping
- alphaproof_loop.py: Ollama → lake build → feedback proof search

Lean Formalization:
- AdjugateMatrix.lean: division-free matrix inversion (291 lines, 3300 jobs, 0 errors)
- det2/det4/det8 via cofactor expansion, all Q16_16
- adjugate, matrixInverse, cayleyTransform
- 7 #eval witnesses all pass

FPGA (Tang Nano 9K):
- voltage_mode_controller.v: 4-mode BRAM (STORE/COMPUTE/APPROX/MORPHIC)
- scale_space_bram.v: 4 Gaussian kernel banks (σ=0.25/0.50/0.75/1.00)
- highs_pivot_accelerator.v: 3-stage pipeline, Q16_16 division, 64-element columns
- blitter_memory_map.v: 8-bit CPU ↔ 32-bit Q16 bridge, full I/O map at $8000
2026-05-28 15:42:14 -05:00

108 lines
3.5 KiB
Verilog

`timescale 1ns / 1ps
// HiGHS Pivot Accelerator for Tang Nano 9K (GW1NR-9C)
// Simplex pivot: column[j] = column[j] / pivot_element
// 3-stage pipeline: load / divide / writeback
// Q16_16 division inline: result = (column_val << 16) / pivot_element
// 64-element column support
module highs_pivot_accelerator (
input wire clk,
input wire rst_n,
input wire start,
input wire [31:0] pivot_element,
input wire [31:0] column_in,
input wire [5:0] column_idx,
output reg [31:0] result,
output reg done,
output reg write_en,
output reg [5:0] write_idx,
output reg [31:0] write_data
);
// State machine
localparam IDLE = 2'b00;
localparam LOAD = 2'b01;
localparam DIVIDE = 2'b10;
localparam WRITEBACK = 2'b11;
reg [1:0] state;
reg [5:0] elem_count; // tracks which element we're processing (0..63)
reg [5:0] elem_count_d1; // delayed count for pipeline
// Pipeline registers
reg [31:0] column_val_reg; // stage 1 output
reg [63:0] dividend; // stage 2: column_val << 16 for Q16_16 division
reg [31:0] pivot_reg; // latched pivot element
// Division result
reg [31:0] div_result;
always @(posedge clk) begin
if (!rst_n) begin
state <= IDLE;
result <= 32'd0;
done <= 1'b0;
write_en <= 1'b0;
write_idx <= 6'd0;
write_data <= 32'd0;
elem_count <= 6'd0;
elem_count_d1 <= 6'd0;
column_val_reg <= 32'd0;
dividend <= 64'd0;
pivot_reg <= 32'd0;
div_result <= 32'd0;
end else begin
// Default: deassert single-cycle pulses
write_en <= 1'b0;
done <= 1'b0;
case (state)
IDLE: begin
if (start) begin
pivot_reg <= pivot_element;
elem_count <= 6'd0;
state <= LOAD;
end
end
LOAD: begin
// Stage 1: Latch column input
column_val_reg <= column_in;
elem_count_d1 <= elem_count;
dividend <= {32'd0, column_in} << 16; // Q16_16 shift
state <= DIVIDE;
end
DIVIDE: begin
// Stage 2: Perform division
// result = (column_val << 16) / pivot_element
if (pivot_reg != 32'd0) begin
div_result <= dividend[63:0] / {32'd0, pivot_reg};
end else begin
div_result <= 32'h7FFFFFFF; // saturate on divide-by-zero
end
state <= WRITEBACK;
end
WRITEBACK: begin
// Stage 3: Write result back
write_en <= 1'b1;
write_idx <= elem_count_d1;
write_data <= div_result;
result <= div_result;
if (elem_count_d1 == 6'd63) begin
// All 64 elements processed
done <= 1'b1;
state <= IDLE;
end else begin
elem_count <= elem_count_d1 + 6'd1;
state <= LOAD;
end
end
endcase
end
end
endmodule