mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
Security & correctness fixes from full adversarial review: Lean (7 fixes): - FixedPoint.lean: guard false theorem with n > 0 precondition - QFactor.lean: remove double-scaling error in energy decrease - AVMIsa/Step.lean: implement addSatQ16/subSatQ16 primitives - BraidEigensolid.lean: fix crossStep second output argument swap - SSMS.lean: complete ACI preservation proof (with rounding caveat) - HouseholderQR.lean: add n > 0 precondition to spectral theorem Verilog (7 fixes): - q16_lut_core.v: fix multiply shift (16 → 32 bits) - q16_lut_top.v: fix valid bit (0 → 1) - cff_accelerator.v: fix SHA-256 padding (len < 448 check) - research_stack_top.v: fix trigger aliasing (unique counters) - Blitter6502OISC_small.v: fix address width (15 → 16 bits) - spatial_hash_bram.v: add OOB write guard - tmr_oepi_safety_fsm.v: fix double-increment race WGSL (6 fixes): - shaders.wgsl: atomicAdd for concurrent writes - frustration_qubo.wgsl: double-buffer + CAS loop - braid_fft.wgsl: workgroupBarrier synchronization - burgers_scar_filter.wgsl: atomic E_bins array Rust (9 fixes): - thermodynamic.rs: Arc::from_raw → Arc::clone (double-free) - thermodynamic.rs: Box::into_raw → Box (leak) - tools/src/lib.rs: shell injection → shlex.quote - ene-node/src/lib.rs: LRU caps, constant-time HMAC, peer caps Python (6 fixes): - similarity/__init__.py: pickle.load → RestrictedUnpickler - AI-Feynman: torch.load → weights_only=True (14 calls) - fetch_arxiv.py, fetch_s2.py: eval → ast.literal_eval - topology.py: os.system → shutil.copy2 - SSH pipe: os.system → base64 pipe Build: lake build 3572 jobs, 0 errors
320 lines
11 KiB
Verilog
320 lines
11 KiB
Verilog
// Research Stack Top-Level Module
|
||
// Unified FPGA design for Tang Nano 9K (GW1NR-9C)
|
||
// Combines: Blitter6502OISC + Q16 LUT + Memory Map + Voltage Controller
|
||
// + Scale Space BRAM + HiGHS Pivot Accelerator
|
||
// + Fractal Box Counter + FD Selector
|
||
// + Spatial Hash BRAM + Density Selector
|
||
|
||
`timescale 1ns / 1ps
|
||
|
||
module research_stack_top (
|
||
input wire clk, // 27 MHz oscillator (pin 52)
|
||
input wire rst_n, // Active-low reset (pin 4)
|
||
input wire user_btn, // Active-low user button (pin 3)
|
||
output wire [5:0] led, // Status LEDs (pins 10,11,13,14,15,16)
|
||
output wire uart_tx, // UART TX (pin 17)
|
||
input wire uart_rx // UART RX (pin 18, unused)
|
||
);
|
||
|
||
// ── Reset & Button ─────────────────────────────────────────────
|
||
wire rst = ~rst_n;
|
||
wire btn_pressed = ~user_btn;
|
||
|
||
// Button debounce
|
||
reg btn_d1, btn_d2;
|
||
reg [19:0] debounce_cnt;
|
||
reg btn_stable, btn_stable_prev;
|
||
wire btn_rise;
|
||
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
btn_d1 <= 0; btn_d2 <= 0;
|
||
debounce_cnt <= 0;
|
||
btn_stable <= 0; btn_stable_prev <= 0;
|
||
end else begin
|
||
btn_d1 <= btn_pressed;
|
||
btn_d2 <= btn_d1;
|
||
if (btn_d2) begin
|
||
if (debounce_cnt < 20'd500000)
|
||
debounce_cnt <= debounce_cnt + 1;
|
||
end else begin
|
||
debounce_cnt <= 0;
|
||
end
|
||
btn_stable <= (debounce_cnt >= 20'd500000);
|
||
btn_stable_prev <= btn_stable;
|
||
end
|
||
end
|
||
assign btn_rise = btn_stable & ~btn_stable_prev;
|
||
|
||
// Auto-start: trigger CPU 100ms after reset (no button needed)
|
||
reg [31:0] auto_start_cnt;
|
||
reg auto_start;
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
auto_start_cnt <= 0;
|
||
auto_start <= 0;
|
||
end else if (!auto_start) begin
|
||
if (auto_start_cnt >= 2700000) begin // 100ms at 27MHz
|
||
auto_start <= 1;
|
||
end else begin
|
||
auto_start_cnt <= auto_start_cnt + 1;
|
||
end
|
||
end
|
||
end
|
||
|
||
// ── Blitter CPU Signals ────────────────────────────────────────
|
||
wire cpu_busy;
|
||
wire [5:0] cpu_led;
|
||
wire cpu_uart_tx;
|
||
wire [7:0] cpu_rdata;
|
||
wire [11:0] cpu_mem_addr;
|
||
wire [7:0] cpu_mem_wdata;
|
||
wire cpu_mem_we;
|
||
|
||
// ── Memory Map Signals ─────────────────────────────────────────
|
||
wire [7:0] map_rdata;
|
||
wire [31:0] map_q16_a;
|
||
wire [31:0] map_q16_b;
|
||
wire [2:0] map_q16_op;
|
||
wire map_q16_trigger;
|
||
wire [1:0] map_voltage_mode;
|
||
wire [1:0] map_scale_select;
|
||
wire [31:0] map_highs_pivot;
|
||
wire map_highs_trigger;
|
||
|
||
// ── Q16 LUT Core Signals ───────────────────────────────────────
|
||
wire [31:0] q16_result;
|
||
wire q16_valid;
|
||
|
||
// ── Voltage Controller Signals ─────────────────────────────────
|
||
wire [31:0] vctrl_dout;
|
||
wire [1:0] vctrl_voltage;
|
||
wire [4:0] vctrl_precision;
|
||
wire vctrl_active;
|
||
|
||
// ── Scale Space BRAM Signals ───────────────────────────────────
|
||
wire [31:0] ss_dout;
|
||
wire [31:0] ss_kernel_sum;
|
||
|
||
// ── HiGHS Pivot Signals ────────────────────────────────────────
|
||
wire [31:0] highs_result;
|
||
wire highs_done;
|
||
wire highs_write_en;
|
||
wire [5:0] highs_write_idx;
|
||
wire [31:0] highs_write_data;
|
||
|
||
// ── Fractal Box Counter Signals ────────────────────────────────
|
||
wire [31:0] frac_fd_q16;
|
||
wire frac_fd_valid;
|
||
wire [1:0] frac_voltage_mode;
|
||
wire frac_mode_valid;
|
||
|
||
// ── Spatial Hash BRAM Signals ─────────────────────────────────
|
||
wire [15:0] sh_cell_density;
|
||
wire [15:0] sh_neighbor_density;
|
||
wire sh_query_done;
|
||
|
||
// ── Spatial Hash Selector Signals ─────────────────────────────
|
||
wire [1:0] sh_voltage_mode;
|
||
wire sh_mode_valid;
|
||
|
||
// ── Q16 LUT: use lower 16 bits of operands ────────────────────
|
||
wire [15:0] q16_a_16 = map_q16_a[15:0];
|
||
wire [15:0] q16_b_16 = map_q16_b[15:0];
|
||
|
||
// ── Result mux: select result source based on address ──────────
|
||
reg [31:0] result_latched;
|
||
reg q16_done_reg;
|
||
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
result_latched <= 0;
|
||
q16_done_reg <= 0;
|
||
end else begin
|
||
if (map_q16_trigger && !q16_busy) begin
|
||
q16_done_reg <= 0;
|
||
end
|
||
if (q16_valid && !q16_done_reg) begin
|
||
result_latched <= q16_result;
|
||
q16_done_reg <= 1;
|
||
end
|
||
end
|
||
end
|
||
|
||
reg q16_busy;
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) q16_busy <= 0;
|
||
else if (map_q16_trigger) q16_busy <= 1;
|
||
else if (q16_valid) q16_busy <= 0;
|
||
end
|
||
|
||
// ── Instantiations ─────────────────────────────────────────────
|
||
|
||
// Blitter6502OISC CPU
|
||
Blitter6502OISC cpu (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.start(auto_start),
|
||
.busy(cpu_busy),
|
||
.led(cpu_led),
|
||
.uart_tx(cpu_uart_tx),
|
||
.mem_we(1'b0),
|
||
.mem_addr(16'd0),
|
||
.mem_wdata(8'd0),
|
||
.mem_rdata()
|
||
);
|
||
|
||
// Blitter Memory Map (8-bit CPU ↔ 32-bit peripherals)
|
||
blitter_memory_map mem_map (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.addr({4'b0, cpu_mem_addr}), // pad 12-bit to 16-bit
|
||
.wdata(cpu_mem_wdata),
|
||
.we(cpu_mem_we),
|
||
.rdata(map_rdata),
|
||
.q16_a(map_q16_a),
|
||
.q16_b(map_q16_b),
|
||
.q16_op(map_q16_op),
|
||
.q16_trigger(map_q16_trigger),
|
||
.voltage_mode(map_voltage_mode),
|
||
.scale_select(map_scale_select),
|
||
.highs_pivot_element(map_highs_pivot),
|
||
.highs_trigger(map_highs_trigger)
|
||
);
|
||
|
||
// Q16 LUT Core (8 operations, 2-stage pipeline)
|
||
q16_lut_core q16 (
|
||
.clk(clk),
|
||
.rst(rst),
|
||
.op_select(map_q16_op),
|
||
.a(q16_a_16),
|
||
.b(q16_b_16),
|
||
.result(q16_result),
|
||
.valid(q16_valid)
|
||
);
|
||
|
||
// Voltage Mode Controller (4 BRAM modes)
|
||
voltage_mode_controller vctrl (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.mode(map_voltage_mode),
|
||
.bram_addr(q16_a_16[9:0]),
|
||
.bram_din(map_q16_b),
|
||
.bram_we(map_q16_trigger),
|
||
.morphic_amp(map_highs_pivot),
|
||
.bram_dout(vctrl_dout),
|
||
.voltage_level(vctrl_voltage),
|
||
.precision_bits(vctrl_precision),
|
||
.active(vctrl_active)
|
||
);
|
||
|
||
// Scale Space BRAM (4 Gaussian kernel banks)
|
||
scale_space_bram ss_bram (
|
||
.clk(clk),
|
||
.we(1'b0),
|
||
.bank_select(map_scale_select),
|
||
.addr(q16_a_16[7:0]),
|
||
.din(32'd0),
|
||
.dout(ss_dout),
|
||
.kernel_sum(ss_kernel_sum)
|
||
);
|
||
|
||
// FIX: Address-decoded trigger enables to prevent aliasing
|
||
// Each module only fires when its specific address range is selected
|
||
wire highs_addr_match = (cpu_mem_addr[11:8] == 4'h4); // $04xx range
|
||
wire frac_addr_match = (cpu_mem_addr[11:8] == 4'h5); // $05xx range
|
||
wire spatial_addr_match = (cpu_mem_addr[11:8] == 4'h6); // $06xx range
|
||
|
||
wire highs_trigger_gated = map_highs_trigger & highs_addr_match;
|
||
wire frac_trigger_gated = map_highs_trigger & frac_addr_match;
|
||
wire spatial_trigger_gated = map_highs_trigger & spatial_addr_match;
|
||
|
||
// HiGHS Pivot Accelerator
|
||
highs_pivot_accelerator highs (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.start(highs_trigger_gated),
|
||
.pivot_element(map_highs_pivot),
|
||
.column_in(map_q16_a),
|
||
.column_idx(map_q16_b[5:0]),
|
||
.result(highs_result),
|
||
.done(highs_done),
|
||
.write_en(highs_write_en),
|
||
.write_idx(highs_write_idx),
|
||
.write_data(highs_write_data)
|
||
);
|
||
|
||
// Fractal Box Counter (DBC algorithm, 8-bit input, Q16_16 FD output)
|
||
fractal_box_counter #(
|
||
.MAX_SCALE(8),
|
||
.DATA_WIDTH(8)
|
||
) frac_bc (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.data_in(map_q16_a[7:0]),
|
||
.data_valid(frac_trigger_gated),
|
||
.data_count(map_q16_b[15:0]),
|
||
.fd_q16(frac_fd_q16),
|
||
.fd_valid(frac_fd_valid)
|
||
);
|
||
|
||
// Fractal FD → Voltage Mode Selector
|
||
// Maps fractal dimension to voltage mode:
|
||
// FD < 2.3 → STORE (0), FD < 2.6 → COMPUTE (1),
|
||
// FD < 2.9 → APPROX (2), FD >= 2.9 → MORPHIC (3)
|
||
fractal_fd_selector frac_sel (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.fd_q16(frac_fd_q16),
|
||
.fd_valid(frac_fd_valid),
|
||
.voltage_mode(frac_voltage_mode),
|
||
.mode_valid(frac_mode_valid)
|
||
);
|
||
|
||
// Spatial Hash BRAM (16×16×16 grid, 8 particles/cell, dual-port)
|
||
// Insert: particle position from map_q16_a[3:0], trigger from map_highs_trigger
|
||
// Query: query position from map_q16_b[3:0], trigger from map_q16_trigger
|
||
spatial_hash_bram spatial_hash (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.particle_x(map_q16_a[3:0]),
|
||
.particle_y(map_q16_a[7:4]),
|
||
.particle_z(map_q16_a[11:8]),
|
||
.particle_valid(spatial_trigger_gated),
|
||
.query_x(map_q16_b[3:0]),
|
||
.query_y(map_q16_b[7:4]),
|
||
.query_z(map_q16_b[11:8]),
|
||
.query_valid(map_q16_trigger),
|
||
.cell_density(sh_cell_density),
|
||
.neighbor_density(sh_neighbor_density),
|
||
.query_done(sh_query_done)
|
||
);
|
||
|
||
// Spatial Hash Density → Voltage Mode Selector
|
||
// Maps particle density to voltage mode:
|
||
// density < 10 → STORE, < 50 → COMPUTE, < 200 → APPROX, >= 200 → MORPHIC
|
||
spatial_hash_selector sh_sel (
|
||
.clk(clk),
|
||
.rst_n(rst_n),
|
||
.density_in(sh_cell_density),
|
||
.density_valid(sh_query_done),
|
||
.voltage_mode(sh_voltage_mode),
|
||
.mode_valid(sh_mode_valid)
|
||
);
|
||
|
||
// ── LED Output ─────────────────────────────────────────────────
|
||
// When CPU is busy: show running pattern (blinking)
|
||
// When CPU is halted: show cpu_led (register values from Blitter)
|
||
// Otherwise: show status
|
||
reg [24:0] heartbeat;
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) heartbeat <= 0;
|
||
else heartbeat <= heartbeat + 1;
|
||
end
|
||
assign led = cpu_busy ? {1'b1, heartbeat[23], 1'b0, heartbeat[21], 1'b0, heartbeat[19]}
|
||
: cpu_led; // Blitter's register output after halt
|
||
|
||
// ── UART ───────────────────────────────────────────────────────
|
||
assign uart_tx = cpu_uart_tx;
|
||
|
||
endmodule
|