|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 Pedro Correia |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + */ |
| 5 | + |
| 6 | +`default_nettype none |
| 7 | + |
| 8 | +module tqvp_TRNG_20RO7FF_PC #( |
| 9 | + parameter SIZE_RO = 6 //size of the RO will be SIZE_RO + 1 inverter gates (7 in this case) |
| 10 | + parameter N_RO = 20 //number of ROs in parallel |
| 11 | + )( |
| 12 | + input clk, // Clock - the TinyQV project clock is normally set to 64MHz. |
| 13 | + input rst_n, // Reset_n - low to reset. |
| 14 | + |
| 15 | + input [7:0] ui_in, // The input PMOD, always available. Note that ui_in[7] is normally used for UART RX. |
| 16 | + // The inputs are synchronized to the clock, note this will introduce 2 cycles of delay on the inputs. |
| 17 | + |
| 18 | + output [7:0] uo_out, // The output PMOD. Each wire is only connected if this peripheral is selected. |
| 19 | + // Note that uo_out[0] is normally used for UART TX. |
| 20 | + |
| 21 | + input [3:0] address, // Address within this peripheral's address space |
| 22 | + |
| 23 | + input data_write, // Data write request from the TinyQV core. |
| 24 | + input [7:0] data_in, // Data in to the peripheral, valid when data_write is high. |
| 25 | + |
| 26 | + output [7:0] data_out // Data out from the peripheral, set this in accordance with the supplied address |
| 27 | +); |
| 28 | + |
| 29 | + reg [SIZE_RO:0] oscillator_ring [N_RO] = 0; |
| 30 | + reg [N_RO:0] oscillator_ring_Q = 0; |
| 31 | + |
| 32 | + reg [7:0] ro_data = 0; |
| 33 | + reg [7:0] shift_reg = 0; |
| 34 | + reg xorA; |
| 35 | + reg counter = 4'b0; |
| 36 | + integer i; |
| 37 | + integer j; |
| 38 | + |
| 39 | + always @(*) begin //Ring oscilators Construction logic |
| 40 | + |
| 41 | + for (j = 0; j < N_RO; j = j + 1) begin |
| 42 | + for (i = 1; i <= SIZE_RO; i = i + 1) begin |
| 43 | + [i]oscillator_ring[j] = ~[i-1]oscillator_ring[j]; |
| 44 | + end |
| 45 | + [0]oscillator_ring[j] = ~[SIZE_RO]oscillator_ring[j]; |
| 46 | + end |
| 47 | + end |
| 48 | + |
| 49 | + always @(posedge clk) begin //sampling FF logic |
| 50 | + for (i = 0; i < N_RO; i = i + 1) begin |
| 51 | + oscillator_ring_Q[i] = [SIZE_RO]oscillator_ring[i] |
| 52 | + end |
| 53 | + end |
| 54 | + |
| 55 | + always @(*) begin // xor logic |
| 56 | + xorA = oscillator_ring_Q[0] ^ oscillator_ring_Q[1] |
| 57 | + for (i = 2; i < N_RO; i = i + 1) begin |
| 58 | + xorA = xorA ^ oscillator_ring_Q[i] |
| 59 | + end |
| 60 | + end |
| 61 | + |
| 62 | + always @(posedge clk or posedge !rst_n) begin //shift register / 8bit data packager |
| 63 | + if (!rst_n) begin |
| 64 | + counter <= 4'b0; |
| 65 | + ro_data <= 8'b0; |
| 66 | + shift_reg <= 8'b0; |
| 67 | + tx_start <= 1'b0; |
| 68 | + end |
| 69 | + else begin |
| 70 | + if (rst_n) begin |
| 71 | + shift_reg[7] <= xorA; |
| 72 | + shift_reg[6] <= shift_reg[7]; |
| 73 | + shift_reg[5] <= shift_reg[6]; |
| 74 | + shift_reg[4] <= shift_reg[5]; |
| 75 | + shift_reg[3] <= shift_reg[4]; |
| 76 | + shift_reg[2] <= shift_reg[3]; |
| 77 | + shift_reg[1] <= shift_reg[2]; |
| 78 | + shift_reg[0] <= shift_reg[1]; |
| 79 | + |
| 80 | + // Counting logic |
| 81 | + if (counter >= 7) begin |
| 82 | + ro_data <= shift_reg; |
| 83 | + tx_start <= 1'b1; |
| 84 | + shift_reg <= 8'b0; |
| 85 | + data_out <= ro_data; |
| 86 | + end |
| 87 | + else begin |
| 88 | + tx_start <= 1'b0; |
| 89 | + end |
| 90 | + end |
| 91 | + end |
| 92 | + end |
| 93 | + |
| 94 | +endmodule |
0 commit comments