123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- module rng
- #(parameter
- nclocks = 1,
- width = 32
- )
- (
-
- input rst_n,
- input sys_clk,
- input read_stb,
- input latch_stb,
- output ready,
- output reg [width-1:0] q,
-
- input [nclocks-1:0] clocks,
- (* keep = 1 *) inout [2:0] rngio
- );
-
- localparam n_osc = 2;
- wire [n_osc:1] osc;
- wire [n_osc:1] osc_s;
-
-
-
- reg [n_osc:1] osc_q;
- reg [n_osc:1] osc_e;
- typedef enum logic [2:0] {
- st_starting,
- st_started,
- st_strobed,
- st_latch,
- st_ready,
- st_stopped
- } state_t;
- state_t state = st_starting;
-
- localparam shutdown_ticks_lg2 = 1;
- reg [shutdown_ticks_lg2-1:0] shutdown_tmr;
- assign ready = (state == st_ready) | (state == st_stopped);
- wire running = (state != st_stopped);
- wire [width-1:0] random_data;
- always @(posedge sys_clk or negedge rst_n)
- if (~rst_n)
- begin
- state <= st_starting;
- osc_q <= 'b0;
- osc_e <= 'b0;
- end
- else
- begin
- osc_q <= ~osc_s;
- osc_e <= 'b0;
- shutdown_tmr <= 'b0;
- case (state)
- st_starting: begin
- osc_e <= osc_e | (osc_s & osc_q);
- if (&osc_e)
- state <= st_started;
- end
- st_started: begin
- if (latch_stb)
- state <= st_strobed;
- end
- st_strobed: begin
- if (latch_stb)
- state <= st_latch;
- end
- st_latch: begin
-
- if (~read_stb)
- begin
- q <= random_data;
- state <= st_ready;
- end
- end
- st_ready: begin
- shutdown_tmr <= shutdown_tmr + latch_stb;
-
-
-
- if (read_stb)
- state <= |shutdown_tmr ? st_latch :
- latch_stb ? st_strobed : st_started;
- else if (latch_stb & &shutdown_tmr)
- state <= st_stopped;
- end
- st_stopped: begin
-
-
-
- if (read_stb)
- state <= st_starting;
- end
- endcase
- end
-
-
-
-
-
- int_osc int_osc
- (
- .clkout ( osc[1] ),
- .oscena ( running )
- );
-
- assign rngio[0] = ~rngio[2] & running;
- assign rngio[1] = ~rngio[0] & running;
- assign rngio[2] = ~rngio[1] & running;
- assign osc[2] = rngio[0];
- synchronizer #(.width(n_osc)) synchro
- (
- .rst_n ( 1'b1 ),
- .clk ( sys_clk ),
- .d ( osc ),
- .q ( osc_s )
- );
-
-
-
-
- localparam poly_width = 33;
- localparam [poly_width-1:0] poly = 33'h0_0000_009d;
- localparam lsfr_max = width > poly_width ? width-1 : poly_width-1;
- wire lsfr_input = ^{osc_s, clocks};
- reg [lsfr_max:0] lsfr;
- always @(posedge sys_clk)
- lsfr <= ({lsfr[lsfr_max-1:0], lsfr_input} ^
- {{(lsfr_max+1){lsfr[poly_width-1]}} & poly});
- assign random_data = lsfr[width-1:0];
- endmodule
|