mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
78 lines
3.7 KiB
Verilog
78 lines
3.7 KiB
Verilog
// Metaprobe Stress Sensor
|
|
// Uses Ring Oscillators to measure physical "frustration" (jitter/noise)
|
|
// Derived from Lean: Semantics/Metaprobe.lean
|
|
// Target: Gowin GW1NR-9 (Tang Nano 9K)
|
|
|
|
`timescale 1ns / 1ps
|
|
|
|
module metaprobe_stress_sensor (
|
|
input wire clk, // Reference clock (e.g. 27MHz)
|
|
input wire rst_n,
|
|
output wire [31:0] stress // Q16.16 stress signal
|
|
);
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Ring Oscillator (RO) Array
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// We use a chain of inverters to create a free-running oscillator.
|
|
// The frequency is sensitive to temperature and voltage noise.
|
|
|
|
wire ro_out;
|
|
wire [7:0] ro_chain;
|
|
|
|
// Inverter chain (keep from being optimized away)
|
|
(* LUT_TYPE="RO" *) assign ro_chain[0] = ~ro_chain[7];
|
|
genvar i;
|
|
generate
|
|
for (i = 1; i < 8; i = i + 1) begin : gen_ro
|
|
assign ro_chain[i] = ~ro_chain[i-1];
|
|
end
|
|
endgenerate
|
|
|
|
assign ro_out = ro_chain[7];
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Jitter Measurement (Frustration)
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Compare RO cycles against ref clock to detect variance (stress).
|
|
|
|
reg [15:0] ro_counter;
|
|
reg [15:0] ref_counter;
|
|
reg [15:0] last_ro_count;
|
|
reg [15:0] jitter_accum;
|
|
|
|
always @(posedge ro_out or negedge rst_n) begin
|
|
if (!rst_n) ro_counter <= 16'd0;
|
|
else ro_counter <= ro_counter + 1;
|
|
end
|
|
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
ref_counter <= 16'd0;
|
|
last_ro_count <= 16'd0;
|
|
jitter_accum <= 16'd0;
|
|
end else begin
|
|
ref_counter <= ref_counter + 1;
|
|
|
|
// Every 2^12 cycles of ref clock, sample RO counter
|
|
if (ref_counter[11:0] == 12'hFFF) begin
|
|
last_ro_count <= ro_counter;
|
|
// Jitter = absolute difference from expected nominal count
|
|
// (Nominal is arbitrary here, we care about change/variance)
|
|
if (ro_counter > last_ro_count)
|
|
jitter_accum <= ro_counter - last_ro_count;
|
|
else
|
|
jitter_accum <= last_ro_count - ro_counter;
|
|
end
|
|
end
|
|
end
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Output Mapping
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Map jitter to Q16.16 stress.
|
|
// baseline jitter = low stress. high variance = high stress.
|
|
|
|
assign stress = {16'b0, jitter_accum}; // Simple mapping for PoC
|
|
|
|
endmodule
|