Research-Stack/4-Infrastructure/hardware/q16_lut_core.v
Brandon Schneider e5fb0a5f4d chore: commit accumulated working tree changes
Lean: update Semantics modules, add new numerics/physics data files
Hardware: update FPGA bitstreams (tangnano9k_uart_loopback)
Infra: k3s-flake tests, netcup-vps configuration, VCN compute substrate
Docs: ARCHITECTURE, specs, citation updates
2026-05-30 00:10:02 -05:00

88 lines
2.9 KiB
Verilog

// Q16_16 LUT Core — Fixed-Point Arithmetic Unit
// Stub based on interface from q16_lut_top.v
// 8 operations, 2-stage pipeline
// Original was generated by Lean Semantics tooling and exists as .json netlist.
// This stub provides the same interface for unified builds.
//
// op_select encoding:
// 000 = add (a + b)
// 001 = sub (a - b)
// 010 = mul (a * b, Q16_16 product)
// 011 = div (a / b, Q16_16 quotient)
// 100 = sqrt (sqrt(a))
// 101 = abs (|a|)
// 110 = min (min(a,b))
// 111 = max (max(a,b))
`timescale 1ns / 1ps
module q16_lut_core (
input wire clk,
input wire rst,
input wire [2:0] op_select,
input wire [15:0] a,
input wire [15:0] b,
output reg [31:0] result,
output reg valid
);
// Pipeline stage 1: decode and latch inputs
reg [2:0] op_reg;
reg [15:0] a_reg;
reg [15:0] b_reg;
reg valid_s1;
// Pipeline stage 2: execute
reg [31:0] result_s2;
reg valid_s2;
// Intermediate computation (combinational)
reg [31:0] compute_result;
always @(*) begin
case (op_reg)
3'b000: compute_result = {16'd0, a_reg} + {16'd0, b_reg}; // add
3'b001: compute_result = {16'd0, a_reg} - {16'd0, b_reg}; // sub
3'b010: compute_result = (a_reg * b_reg); // mul (simplified)
3'b011: begin // div
if (b_reg != 16'd0)
compute_result = ({16'd0, a_reg} << 16) / {16'd0, b_reg};
else
compute_result = 32'h7FFFFFFF; // saturate
end
3'b100: compute_result = {16'd0, a_reg}; // sqrt (passthrough stub)
3'b101: compute_result = a_reg[15] ? {16'd0, (~a_reg + 16'd1)} : {16'd0, a_reg}; // abs
3'b110: compute_result = (a_reg <= b_reg) ? {16'd0, a_reg} : {16'd0, b_reg}; // min
3'b111: compute_result = (a_reg >= b_reg) ? {16'd0, a_reg} : {16'd0, b_reg}; // max
endcase
end
// Pipeline registers
always @(posedge clk) begin
if (rst) begin
op_reg <= 3'd0;
a_reg <= 16'd0;
b_reg <= 16'd0;
valid_s1 <= 1'b0;
result_s2 <= 32'd0;
valid_s2 <= 1'b0;
result <= 32'd0;
valid <= 1'b0;
end else begin
// Stage 1: latch inputs
op_reg <= op_select;
a_reg <= a;
b_reg <= b;
valid_s1 <= 1'b1; // always valid after first cycle
// Stage 2: compute
result_s2 <= compute_result;
valid_s2 <= valid_s1;
// Output
result <= result_s2;
valid <= valid_s2;
end
end
endmodule