module rnd_vec_gen(
clk,
init,
save,
restore,
next,
out
);
parameter OUT_SIZE = 16; // size of output port, independent of LFSR register size
parameter LFSR_LENGTH = 55; // LFSR
parameter LFSR_FEEDBACK = 24; // definition
input clk;
input init; // positive initialization strobe, synchronous to clock, its length will determine initial state
input save,restore,next; // strobes for required events: positive, one clock cycle long
reg init2;
output [OUT_SIZE-1:0] out;
wire [OUT_SIZE-1:0] out;
reg [OUT_SIZE-1:0] rndbase_main [0:LFSR_LENGTH-1];
reg [OUT_SIZE-1:0] rndbase_store [0:LFSR_LENGTH-1];
assign out = rndbase_main[0];
initial
begin : clr_arrays_for_sim
integer i;
for(i=0;i<LFSR_LENGTH;i=i+1)
begin
rndbase_main [i] = 'd0;
rndbase_store[i] = 'd0;
end
end
always @(posedge clk)
begin
init2 <= init;
if( init && !init2 ) // begin of initialization
begin
rndbase_main[0][0] <= 1'b1; // any non-zero init possible
end
else if( init && init2 ) // continue of initialization
begin
shift_lfsr;
end
else // no init, normal work
begin
if( restore ) // restore event: higher priority
begin : blk1
integer i;
for(i=0;i<LFSR_LENGTH;i=i+1)
rndbase_main[i] <= rndbase_store[i];
end
else
begin
if( next ) // step to next value
begin
shift_lfsr;
end
if( save ) // save current state
begin : blk2
integer j;
for(j=0;j<LFSR_LENGTH;j=j+1)
rndbase_store[j] <= rndbase_main[j];
end
end
end
end
/* function [LFSR_LENGTH-1:0] shift_lfsr;
input [LFSR_LENGTH-1:0] old_lfsr;
begin
if( |old_lfsr ) // prevent spurious stalls if all LFSR is zeros
shift_lfsr[LFSR_LENGTH-1:0] = { old_lfsr[LFSR_LENGTH-2:0], old_lfsr[LFSR_LENGTH-1]^old_lfsr[LFSR_FEEDBACK-1] };
else
shift_lfsr[LFSR_LENGTH-1:0] = 2'd1;
end
endfunction
*/
task shift_lfsr;
begin : blk3
reg [OUT_SIZE-1:0] sum;
reg [LFSR_LENGTH-1:0] lsbs;
integer i;
for(i=0;i<LFSR_LENGTH;i=i+1)
lsbs[i] = rndbase_main[i][0];
sum = rndbase_main[LFSR_LENGTH-1] + rndbase_main[LFSR_FEEDBACK-1];
// integer j;
for(i=1;i<LFSR_LENGTH;i=i+1)
rndbase_main[i] <= rndbase_main[i-1];
rndbase_main[0] <= { sum[OUT_SIZE-1:1], (|lsbs)?sum[0]:1'b1 };
end
endtask
endmodule