feat: add four 90-ring entropy generators with spatial and temporal XOR (FPGA v3)
This commit is contained in:
parent
504b00752a
commit
585e755c66
9 changed files with 389 additions and 217 deletions
92
fpga/rtl/entropy_generator.v
Normal file
92
fpga/rtl/entropy_generator.v
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// One entropy generator: RINGS ring oscillators whose enhanced outputs are each sampled
|
||||
// every clock and XORed together (spatial XOR, pipelined), then XORed over `temporal`
|
||||
// consecutive clocks. The output bit is held for `temporal` clocks, so capturing it with
|
||||
// decimation = temporal yields every output bit exactly once.
|
||||
//
|
||||
// XOR combining multiplies the relative predictabilities (2P-1) of independent inputs, so
|
||||
// the ring count and temporal factor set the residual bias and correlation of the output.
|
||||
//
|
||||
// A selected ring's sampled outputs and its raw tap are exposed for characterization.
|
||||
module entropy_generator #(
|
||||
parameter RINGS = 90 // at most 256 (four 4:1 XOR stages)
|
||||
) (
|
||||
input wire clk,
|
||||
input wire enable, // low stops all rings
|
||||
input wire [3:0] temporal, // consecutive bits XORed per output bit, 1-8
|
||||
input wire [7:0] ring_select, // ring exposed on the characterization outputs
|
||||
output reg out_bit, // processed output, held for `temporal` clocks
|
||||
output wire spatial_bit, // XOR of all rings, one per clock
|
||||
output reg ring_enhanced,
|
||||
output reg ring_tap,
|
||||
output wire ring_raw_tap // unsynchronized, for frequency counting
|
||||
);
|
||||
|
||||
wire [RINGS-1:0] raw_enhanced, raw_tap;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < RINGS; i = i + 1) begin : ring
|
||||
ring_osc #(.LENGTH(9 + 3 * (i % 3))) osc (
|
||||
.enable(enable), .first_tap(raw_tap[i]), .enhanced(raw_enhanced[i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// sample_raw catches the asynchronous ring signals and may go metastable;
|
||||
// sample_sync resolves it. The SDC file cuts timing into sample_raw.
|
||||
reg [RINGS-1:0] sample_raw, sample_sync, tap_raw, tap_sync;
|
||||
always @(posedge clk) begin
|
||||
sample_raw <= raw_enhanced;
|
||||
sample_sync <= sample_raw;
|
||||
tap_raw <= raw_tap;
|
||||
tap_sync <= tap_raw;
|
||||
end
|
||||
|
||||
// Spatial XOR: four registered stages of 4-input XORs (256 -> 64 -> 16 -> 4 -> 1).
|
||||
reg [255:0] level0;
|
||||
reg [63:0] level1;
|
||||
reg [15:0] level2;
|
||||
reg [3:0] level3;
|
||||
reg level4;
|
||||
integer j;
|
||||
|
||||
always @(*) begin
|
||||
level0 = 256'd0;
|
||||
level0[RINGS-1:0] = sample_sync;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (j = 0; j < 64; j = j + 1) level1[j] <= ^level0[4*j +: 4];
|
||||
for (j = 0; j < 16; j = j + 1) level2[j] <= ^level1[4*j +: 4];
|
||||
for (j = 0; j < 4; j = j + 1) level3[j] <= ^level2[4*j +: 4];
|
||||
level4 <= ^level3;
|
||||
end
|
||||
|
||||
assign spatial_bit = level4;
|
||||
|
||||
// Temporal XOR over `temporal` consecutive spatial bits.
|
||||
reg [3:0] phase = 4'd0;
|
||||
reg accumulator = 1'b0;
|
||||
wire last = (phase >= temporal - 4'd1) || (temporal == 4'd0);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (last) begin
|
||||
out_bit <= accumulator ^ spatial_bit;
|
||||
accumulator <= 1'b0;
|
||||
phase <= 4'd0;
|
||||
end else begin
|
||||
accumulator <= accumulator ^ spatial_bit;
|
||||
phase <= phase + 4'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// Characterization taps
|
||||
|
||||
always @(posedge clk) begin
|
||||
ring_enhanced <= sample_sync[ring_select];
|
||||
ring_tap <= tap_sync[ring_select];
|
||||
end
|
||||
|
||||
assign ring_raw_tap = raw_tap[ring_select];
|
||||
|
||||
endmodule
|
||||
Loading…
Add table
Add a link
Reference in a new issue