92 lines
3.3 KiB
Verilog
92 lines
3.3 KiB
Verilog
// 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
|