feat: add 16-ring bank, sampled XOR, pair capture and frequency counter (FPGA v2)
This commit is contained in:
parent
d51a6c0ca8
commit
504b00752a
12 changed files with 654 additions and 347 deletions
|
|
@ -1,12 +1,17 @@
|
|||
// Board-independent STRIX logic: entropy generator, raw capture and the SPI register
|
||||
// interface to the SAMD21.
|
||||
// Board-independent STRIX logic: ring bank, source selection, raw capture, frequency
|
||||
// counter and the SPI register interface to the SAMD21.
|
||||
//
|
||||
// SPI protocol (mode 0, one transaction per ss_n low period): the first byte is a command,
|
||||
// bit 7 = read (1) or write (0), bits 6:0 = register address. A write stores the following
|
||||
// byte(s) in that register. A read returns the register in every following byte; DATA
|
||||
// advances through the capture buffer with each byte, continuing across transactions.
|
||||
//
|
||||
// Capture sources (6-bit codes): 0x00-0x0F enhanced output of ring i, 0x10-0x1F single
|
||||
// tap of ring i, 0x20-0x2F XOR of the enhanced outputs of rings 0..n-1 for n = 1..16.
|
||||
// All sources are taken after sampling.
|
||||
module strix_core #(
|
||||
parameter CAPTURE_ADDR_WIDTH = 15
|
||||
parameter CAPTURE_ADDR_WIDTH = 15,
|
||||
parameter FREQ_GATE_BITS = 24
|
||||
) (
|
||||
input wire clk,
|
||||
input wire reset,
|
||||
|
|
@ -17,27 +22,62 @@ module strix_core #(
|
|||
output wire capture_done
|
||||
);
|
||||
|
||||
localparam [7:0] VERSION = 8'h01;
|
||||
localparam [7:0] VERSION = 8'h02;
|
||||
localparam RINGS = 16;
|
||||
|
||||
localparam [6:0] REG_ID0 = 7'h00, // "STRX"
|
||||
REG_ID1 = 7'h01,
|
||||
REG_ID2 = 7'h02,
|
||||
REG_ID3 = 7'h03,
|
||||
REG_VERSION = 7'h04,
|
||||
REG_SOURCE = 7'h08, // 0 tap A, 1 enhanced A, 2 enhanced B, 3 pair
|
||||
REG_DECIM_HIGH = 7'h09,
|
||||
REG_DECIM_LOW = 7'h0A,
|
||||
REG_CONTROL = 7'h0B, // write: bit 0 start capture, bit 1 rewind DATA
|
||||
REG_STATUS = 7'h0C, // bit 0 busy, bit 1 done
|
||||
REG_DATA = 7'h10;
|
||||
localparam [6:0] REG_ID0 = 7'h00, // "STRX"
|
||||
REG_ID1 = 7'h01,
|
||||
REG_ID2 = 7'h02,
|
||||
REG_ID3 = 7'h03,
|
||||
REG_VERSION = 7'h04,
|
||||
REG_FREQ_GATE = 7'h05, // read-only: gate is 2^value clk cycles
|
||||
REG_SOURCE_A = 7'h08,
|
||||
REG_DECIM_HIGH = 7'h09,
|
||||
REG_DECIM_LOW = 7'h0A,
|
||||
REG_CONTROL = 7'h0B, // write: bit 0 start capture, bit 1 rewind DATA,
|
||||
// bit 2 start frequency measurement
|
||||
REG_STATUS = 7'h0C, // bit 0 capture busy, bit 1 capture done,
|
||||
// bit 2 frequency busy, bit 3 frequency valid
|
||||
REG_SOURCE_B = 7'h0D,
|
||||
REG_MODE = 7'h0E, // bit 0 pair capture (A and B per sample)
|
||||
REG_RING_COUNT = 7'h0F,
|
||||
REG_DATA = 7'h10,
|
||||
REG_FREQ_SELECT = 7'h11, // ring to measure
|
||||
REG_FREQ_COUNT3 = 7'h12, // prescaled edge count, most significant byte first
|
||||
REG_FREQ_COUNT2 = 7'h13,
|
||||
REG_FREQ_COUNT1 = 7'h14,
|
||||
REG_FREQ_COUNT0 = 7'h15;
|
||||
|
||||
// Entropy and capture
|
||||
// Ring bank and source selection
|
||||
|
||||
wire [3:0] samples;
|
||||
wire [RINGS-1:0] enhanced, first_tap, raw_tap;
|
||||
|
||||
entropy_gen generator (.clk(clk), .enable(1'b1), .samples(samples));
|
||||
ring_bank #(.RINGS(RINGS)) bank (
|
||||
.clk(clk), .enable(1'b1),
|
||||
.enhanced(enhanced), .first_tap(first_tap), .raw_tap(raw_tap)
|
||||
);
|
||||
|
||||
reg [1:0] source;
|
||||
reg [RINGS-1:0] xor_prefix_comb, xor_prefix;
|
||||
integer j;
|
||||
always @(*) begin
|
||||
xor_prefix_comb[0] = enhanced[0];
|
||||
for (j = 1; j < RINGS; j = j + 1)
|
||||
xor_prefix_comb[j] = xor_prefix_comb[j-1] ^ enhanced[j];
|
||||
end
|
||||
|
||||
reg [5:0] source_a, source_b;
|
||||
reg bit_a, bit_b;
|
||||
wire [63:0] all_sources = {16'd0, xor_prefix, first_tap, enhanced};
|
||||
|
||||
always @(posedge clk) begin
|
||||
xor_prefix <= xor_prefix_comb;
|
||||
bit_a <= all_sources[source_a];
|
||||
bit_b <= all_sources[source_b];
|
||||
end
|
||||
|
||||
// Capture
|
||||
|
||||
reg pair_mode;
|
||||
reg [15:0] decimation;
|
||||
reg capture_start;
|
||||
wire capture_busy;
|
||||
|
|
@ -45,12 +85,24 @@ module strix_core #(
|
|||
wire [7:0] capture_byte;
|
||||
|
||||
raw_capture #(.ADDR_WIDTH(CAPTURE_ADDR_WIDTH)) capture (
|
||||
.clk(clk), .reset(reset), .samples(samples), .source(source),
|
||||
.clk(clk), .reset(reset), .bit_a(bit_a), .bit_b(bit_b), .pair_mode(pair_mode),
|
||||
.decimation(decimation), .start(capture_start),
|
||||
.busy(capture_busy), .done(capture_done),
|
||||
.read_addr(prefetch_addr), .read_data(capture_byte)
|
||||
);
|
||||
|
||||
// Frequency counter
|
||||
|
||||
reg [3:0] freq_select;
|
||||
reg freq_start;
|
||||
wire freq_busy, freq_valid;
|
||||
wire [31:0] freq_count;
|
||||
|
||||
freq_counter #(.GATE_BITS(FREQ_GATE_BITS)) counter (
|
||||
.clk(clk), .reset(reset), .signal(raw_tap[freq_select]), .start(freq_start),
|
||||
.busy(freq_busy), .valid(freq_valid), .count(freq_count)
|
||||
);
|
||||
|
||||
// SPI
|
||||
|
||||
wire selected, rx_valid, rx_is_first, tx_loaded;
|
||||
|
|
@ -76,25 +128,38 @@ module strix_core #(
|
|||
|
||||
always @(*) begin
|
||||
case (reg_addr)
|
||||
REG_ID0: tx_byte = "S";
|
||||
REG_ID1: tx_byte = "T";
|
||||
REG_ID2: tx_byte = "R";
|
||||
REG_ID3: tx_byte = "X";
|
||||
REG_VERSION: tx_byte = VERSION;
|
||||
REG_SOURCE: tx_byte = {6'd0, source};
|
||||
REG_DECIM_HIGH: tx_byte = decimation[15:8];
|
||||
REG_DECIM_LOW: tx_byte = decimation[7:0];
|
||||
REG_STATUS: tx_byte = {6'd0, capture_done, capture_busy};
|
||||
REG_DATA: tx_byte = capture_byte;
|
||||
default: tx_byte = 8'h00;
|
||||
REG_ID0: tx_byte = "S";
|
||||
REG_ID1: tx_byte = "T";
|
||||
REG_ID2: tx_byte = "R";
|
||||
REG_ID3: tx_byte = "X";
|
||||
REG_VERSION: tx_byte = VERSION;
|
||||
REG_FREQ_GATE: tx_byte = FREQ_GATE_BITS;
|
||||
REG_SOURCE_A: tx_byte = {2'd0, source_a};
|
||||
REG_DECIM_HIGH: tx_byte = decimation[15:8];
|
||||
REG_DECIM_LOW: tx_byte = decimation[7:0];
|
||||
REG_STATUS: tx_byte = {4'd0, freq_valid, freq_busy, capture_done, capture_busy};
|
||||
REG_SOURCE_B: tx_byte = {2'd0, source_b};
|
||||
REG_MODE: tx_byte = {7'd0, pair_mode};
|
||||
REG_RING_COUNT: tx_byte = RINGS;
|
||||
REG_DATA: tx_byte = capture_byte;
|
||||
REG_FREQ_SELECT: tx_byte = {4'd0, freq_select};
|
||||
REG_FREQ_COUNT3: tx_byte = freq_count[31:24];
|
||||
REG_FREQ_COUNT2: tx_byte = freq_count[23:16];
|
||||
REG_FREQ_COUNT1: tx_byte = freq_count[15:8];
|
||||
REG_FREQ_COUNT0: tx_byte = freq_count[7:0];
|
||||
default: tx_byte = 8'h00;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
capture_start <= 1'b0;
|
||||
freq_start <= 1'b0;
|
||||
if (reset) begin
|
||||
source <= 2'd3;
|
||||
source_a <= 6'h00;
|
||||
source_b <= 6'h01;
|
||||
pair_mode <= 1'b0;
|
||||
decimation <= 16'd1;
|
||||
freq_select <= 4'd0;
|
||||
is_read <= 1'b0;
|
||||
reg_addr <= 7'd0;
|
||||
bytes_read <= {CAPTURE_ADDR_WIDTH{1'b0}};
|
||||
|
|
@ -113,12 +178,16 @@ module strix_core #(
|
|||
bytes_read <= bytes_read + 1'b1;
|
||||
end else if (!is_read) begin
|
||||
case (reg_addr)
|
||||
REG_SOURCE: source <= rx_byte[1:0];
|
||||
REG_DECIM_HIGH: decimation[15:8] <= rx_byte;
|
||||
REG_DECIM_LOW: decimation[7:0] <= rx_byte;
|
||||
REG_SOURCE_A: source_a <= rx_byte[5:0];
|
||||
REG_SOURCE_B: source_b <= rx_byte[5:0];
|
||||
REG_MODE: pair_mode <= rx_byte[0];
|
||||
REG_DECIM_HIGH: decimation[15:8] <= rx_byte;
|
||||
REG_DECIM_LOW: decimation[7:0] <= rx_byte;
|
||||
REG_FREQ_SELECT: freq_select <= rx_byte[3:0];
|
||||
REG_CONTROL: begin
|
||||
if (rx_byte[0]) capture_start <= 1'b1;
|
||||
if (rx_byte[0] || rx_byte[1]) bytes_read <= {CAPTURE_ADDR_WIDTH{1'b0}};
|
||||
if (rx_byte[2]) freq_start <= 1'b1;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue