diff --git a/hw/application_fpga/core/trng/rtl/figaro.v b/hw/application_fpga/core/trng/rtl/figaro.v index 70ba469..e72caf8 100644 --- a/hw/application_fpga/core/trng/rtl/figaro.v +++ b/hw/application_fpga/core/trng/rtl/figaro.v @@ -31,24 +31,68 @@ module figaro( //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- + // API localparam ADDR_STATUS = 8'h09; localparam STATUS_READY_BIT = 0; - - localparam ADDR_SAMPLE_RATE = 8'h10; - localparam ADDR_ENTROPY = 8'h20; + // Total number of ROSCs will be 2 x NUM_ROSC. + localparam SAMPLE_RATE = 16'h1000; + localparam NUM_ROSC = 16; + + localparam CTRL_SAMPLE1 = 0; + localparam CTRL_SAMPLE2 = 1; + localparam CTRL_DATA_READY = 2; + + + //---------------------------------------------------------------- + // Registers with associated wires. + //---------------------------------------------------------------- + reg [16 : 0] cycle_ctr_reg; + reg [16 : 0] cycle_ctr_new; + reg cycle_ctr_done; + reg cycle_ctr_rst; + + reg [4 : 0] bit_ctr_reg; + reg [4 : 0] bit_ctr_new; + reg bit_ctr_we; + + reg [31 : 0] entropy_reg; + reg [31 : 0] entropy_new; + reg entropy_we; + + reg [1 : 0] sample1_reg; + reg [1 : 0] sample1_new; + reg sample1_we; + + reg [1 : 0] sample2_reg; + reg [1 : 0] sample2_new; + reg sample2_we; + + reg data_ready_reg; + reg data_ready_new; + reg data_ready_we; + reg data_ready_set; + reg data_ready_rst; + + reg [1 : 0] rosc_ctrl_reg; + reg [1 : 0] rosc_ctrl_new; + reg rosc_ctrl_we; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- - reg core_read_entropy; - reg core_set_sample_rate; - wire [31 : 0] core_entropy; - wire core_ready; reg [31 : 0] tmp_read_data; reg tmp_ready; + /* verilator lint_off UNOPTFLAT */ + wire [(NUM_ROSC - 1) : 0] f; + /* verilator lint_on UNOPTFLAT */ + + /* verilator lint_off UNOPTFLAT */ + wire [(NUM_ROSC - 1) : 0] g; + /* verilator lint_on UNOPTFLAT */ + //---------------------------------------------------------------- // Concurrent connectivity for ports etc. @@ -58,17 +102,66 @@ module figaro( //---------------------------------------------------------------- - // core instantiation. + // oscillators. + // + // 32 single inverters, each connect to itself. //---------------------------------------------------------------- - figaro_core core( - .clk(clk), - .reset_n(reset_n), - .read_entropy(core_read_entropy), - .set_sample_rate(core_set_sample_rate), - .sample_rate(write_data[23 : 0]), - .entropy(core_entropy), - .ready(core_ready) - ); + genvar i; + generate + for(i = 0 ; i < NUM_ROSC ; i = i + 1) + begin: oscillators + /* verilator lint_off PINMISSING */ + (* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv_f (.I0(f[i]), .O(f[i])); + + (* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv_g (.I0(g[i]), .O(g[i])); + /* verilator lint_off PINMISSING */ + end + endgenerate + + + //--------------------------------------------------------------- + // reg_update + //--------------------------------------------------------------- + always @(posedge clk) + begin : reg_update + if (!reset_n) begin + cycle_ctr_reg <= 16'h0; + bit_ctr_reg <= 5'h0; + sample1_reg <= 2'h0; + sample2_reg <= 2'h0; + entropy_reg <= 32'h0; + data_ready_reg <= 1'h0; + rosc_ctrl_reg <= CTRL_SAMPLE1; + end + + else begin + cycle_ctr_reg <= cycle_ctr_new; + + if (bit_ctr_we) begin + bit_ctr_reg <= bit_ctr_new; + end + + if (sample1_we) begin + sample1_reg <= sample1_new; + end + + if (sample2_we) begin + sample2_reg <= sample2_new; + end + + if (entropy_we) begin + entropy_reg <= entropy_new; + end + + if (data_ready_we) begin + data_ready_reg <= data_ready_new; + end + + if (rosc_ctrl_we) begin + rosc_ctrl_reg <= rosc_ctrl_new; + end + end + end //---------------------------------------------------------------- @@ -78,32 +171,133 @@ module figaro( //---------------------------------------------------------------- always @* begin : api - core_read_entropy = 1'h0; - core_set_sample_rate = 1'h0; - tmp_read_data = 32'h0; - tmp_ready = 1'h0; + data_ready_rst = 1'h0; + tmp_read_data = 32'h0; + tmp_ready = 1'h0; if (cs) begin tmp_ready = 1'h1; - if (we) begin - if (address == ADDR_SAMPLE_RATE) begin - core_set_sample_rate = 1'h1; - end - end - - else begin + if (!we) begin if (address == ADDR_STATUS) begin - tmp_read_data = {31'h0, core_ready}; + tmp_read_data = {31'h0, data_ready_reg}; end if (address == ADDR_ENTROPY) begin - tmp_read_data = core_entropy; - core_read_entropy = 1'h1; + tmp_read_data = entropy_reg; + data_ready_rst = 1'h1; end end end end // api + + + //---------------------------------------------------------------- + // data_ready_logic + //---------------------------------------------------------------- + always @* + begin : data_ready_logic + data_ready_new = 1'h0; + data_ready_we = 1'h0; + + if (data_ready_set) begin + data_ready_new = 1'h1; + data_ready_we = 1'h1; + + end else if (data_ready_rst) begin + data_ready_new = 1'h0; + data_ready_we = 1'h1; + end + end + + + //---------------------------------------------------------------- + // cycle_ctr_logic + //---------------------------------------------------------------- + always @* + begin : cycle_ctr_logic + cycle_ctr_done = 1'h0; + cycle_ctr_new = cycle_ctr_reg + 1'h1; + + if (cycle_ctr_rst) begin + cycle_ctr_new = 24'h0; + end + + if (cycle_ctr_reg == SAMPLE_RATE) begin + cycle_ctr_done = 1'h1; + end + end + + + //---------------------------------------------------------------- + // rosc_ctrl_logic + //---------------------------------------------------------------- + always @* + begin : rosc_ctrl_logic + reg xor_f; + reg xor_g; + reg xor_sample1; + reg xor_sample2; + + sample1_we = 1'h0; + sample2_we = 1'h0; + cycle_ctr_rst = 1'h0; + data_ready_set = 1'h0; + entropy_we = 1'h0; + bit_ctr_new = 6'h0; + bit_ctr_we = 1'h0; + rosc_ctrl_new = CTRL_SAMPLE1; + rosc_ctrl_we = 1'h0; + + xor_f = ^f; + xor_g = ^g; + xor_sample1 = ^sample1_reg; + xor_sample2 = ^sample2_reg; + + sample1_new = {sample1_reg[0], xor_f}; + sample2_new = {sample2_reg[0], xor_g}; + entropy_new = {entropy_reg[30 : 0], xor_sample2}; + + if (bit_ctr_reg == 31) begin + data_ready_set = 1'h1; + end + + case (rosc_ctrl_reg) + CTRL_SAMPLE1: begin + if (cycle_ctr_done) begin + cycle_ctr_rst = 1'h1; + sample1_we = 1'h1; + sample2_we = 1'h1; + rosc_ctrl_new = CTRL_SAMPLE2; + rosc_ctrl_we = 1'h1; + end + end + + CTRL_SAMPLE2: begin + if (cycle_ctr_done) begin + cycle_ctr_rst = 1'h1; + sample1_we = 1'h1; + sample2_we = 1'h1; + rosc_ctrl_new = CTRL_DATA_READY; + rosc_ctrl_we = 1'h1; + end + end + + CTRL_DATA_READY: begin + if (xor_sample1 ^ xor_sample2) begin + entropy_we = 1'h1; + bit_ctr_new = bit_ctr_reg + 1'h1; + bit_ctr_we = 1'h1; + end + rosc_ctrl_new = CTRL_SAMPLE1; + rosc_ctrl_we = 1'h1; + end + + default: begin + end + endcase // case (rosc_ctrl_reg) + end + endmodule // figaro //======================================================================