mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
Finally converging on a decent lfsr module
- Lesson 1: Keep it simple!!! - Lesson 2: Make each program do one thing well. (unix) - Lesson 3: Make module dynamic (parameters and ifdefs are horrible!) - Lesson 4: Synthesis can remove bits set to 0 in design... - Lesson 5: Dynamic binding/programmabiility is better!
This commit is contained in:
parent
26caf997d3
commit
9410821818
@ -1,58 +1,85 @@
|
||||
//#############################################################################
|
||||
//# Function: Random number generator #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
//
|
||||
// References:
|
||||
// https://users.ece.cmu.edu/~koopman/lfsr/index.html
|
||||
//
|
||||
//############################################################################
|
||||
module oh_random
|
||||
#(parameter N = 32 //support multiple of 32 for now...
|
||||
/******************************************************************************
|
||||
* Function: Linear Feedback Shift Register (Galois)
|
||||
* Author: Andreas Olofsson
|
||||
* License: MIT (see LICENSE file in OH! repository)
|
||||
*
|
||||
* Documentation:
|
||||
*
|
||||
* - A generic Galois LFSR with taps and seeds feed in externally to enable
|
||||
* dynamically programming the taps and seed. Shift is from MSB to LSB,
|
||||
* feedback bit is from LSB.
|
||||
*
|
||||
* - The lsfr updates when enable is set to 1.
|
||||
*
|
||||
* - Any non-zero seed value is legal.
|
||||
*
|
||||
* - Driving taps externally is only practical with GALOIS configuration,
|
||||
* since the massive xor tree would be prohibitive with FIBONACCI.
|
||||
|
||||
* - Example terms from: https://users.ece.cmu.edu/~koopman/lfsr/index.html
|
||||
*
|
||||
* N POLYNOMIAL
|
||||
* -------------------
|
||||
* 4 9
|
||||
* 5 12
|
||||
* 6 21
|
||||
* 7 41
|
||||
* 8 8E
|
||||
* 9 108
|
||||
* 10 204
|
||||
* 11 402
|
||||
* 12 829
|
||||
* 13 100D
|
||||
* 14 2015
|
||||
* 15 4001
|
||||
* 16 8016
|
||||
* 17 10004
|
||||
* 18 20013
|
||||
* 19 40013
|
||||
* 20 80004
|
||||
* 21 100002
|
||||
* 22 200001
|
||||
* 23 400010
|
||||
* 24 80000D
|
||||
* 25 1000004
|
||||
* 26 2000023
|
||||
* 27 4000013
|
||||
* 28 8000004
|
||||
* 29 10000002
|
||||
* 30 20000029
|
||||
* 31 40000004
|
||||
* 32 80000057
|
||||
* 58 200000000000031
|
||||
* 64 800000000000000D
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
module oh_lfsr
|
||||
#(parameter N = 32, // length of LFSR
|
||||
parameter TYPE = "GALOIS" // lfsr type (only galois supported ...)
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input nreset, //async reset
|
||||
input en, // enable counter
|
||||
input [1:0] mode,// 0=fibonacci,1=galois
|
||||
input lsbfirst,// 1=shift from lsb, 0=shift from msb
|
||||
input [N-1:0] taps, // taps
|
||||
input [N-1:0] seed, // seed
|
||||
input [N-1:0] mask, // mask output (1 = active)
|
||||
output [N-1:0] out // output value
|
||||
input clk,
|
||||
input nreset, //async reset
|
||||
input en, // enables (advances) lfsr
|
||||
input [N-1:0] taps, // taps
|
||||
input [N-1:0] seed, // seed
|
||||
output reg [N-1:0] out // output value/state vector
|
||||
);
|
||||
|
||||
// TODO: support non-multiples of 32
|
||||
reg [N-1:0] lfsr_reg[0:N/32-1];
|
||||
wire [N-1:0] lfsr_in[0:N/32-1];
|
||||
wire [N-1:0] taps_sel[0:N/32-1];
|
||||
wire [N/32-1:0] feedback;
|
||||
|
||||
// instantiate multiple 32bit rngs
|
||||
genvar i,j;
|
||||
generate
|
||||
for(i=0;i<(N/32);i=i+1) begin
|
||||
//taps
|
||||
assign taps_sel[i] = entaps ? taps[(i+1)*32-1:i*32]: 32'h80000057 << 1;
|
||||
//lfsr reg
|
||||
always @(posedge clk or negedge nreset)
|
||||
if (TYPE == "GALOIS") begin
|
||||
always @ (posedge clk or negedge nreset)
|
||||
if(~nreset)
|
||||
lfsr_reg[i] <= seed[(i+1)*32-1:i*32];
|
||||
out[N-1:0] <= seed[N-1:0];
|
||||
else if(en)
|
||||
lfsr_reg[i] <= lfsr_in[i];
|
||||
// feeback
|
||||
assign feedback[i] = lfsr_reg[i][31];
|
||||
assign lfsr_in[i][0] = feedback[i];
|
||||
for(j=1;j<32;j=j+1) begin
|
||||
assign lfsr_in[i][j] = taps_sel[i][j] ? (lfsr_reg[i][j-1] ^ feedback[i]) :
|
||||
lfsr_reg[i][j-1];
|
||||
|
||||
end
|
||||
assign out[(i+1)*32-1:i*32] = mask[(i+1)*32-1:i*32] & lfsr_reg[i];
|
||||
end // for (i=0;<N/32;i=i+1)
|
||||
out[N-1:0] <= ({(N){out[0]}} & taps[N-1:0]) ^
|
||||
(out[N-1:0] >> 1);
|
||||
end
|
||||
else if (TYPE == "FIBONACCI") begin
|
||||
initial
|
||||
$display("UNSUPPORTED");
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
endmodule // oh_random
|
||||
endmodule // oh_lfsr
|
||||
|
@ -1,53 +0,0 @@
|
||||
//#############################################################################
|
||||
//# Function: Random number generator #
|
||||
//#############################################################################
|
||||
//# Author: Andreas Olofsson #
|
||||
//# License: MIT (see LICENSE file in OH! repository) #
|
||||
//#############################################################################
|
||||
|
||||
module oh_random
|
||||
#(parameter N = 32 //support multiple of 32 for now...
|
||||
)
|
||||
(
|
||||
input clk,
|
||||
input nreset, //async reset
|
||||
input en, // enable counter
|
||||
input entaps, // enable taps input
|
||||
input [N-1:0] taps, // user driven taps
|
||||
input [N-1:0] seed, // seed
|
||||
input [N-1:0] mask, // mask output (1 = active)
|
||||
output [N-1:0] out //random output pulse
|
||||
);
|
||||
|
||||
// TODO: support non-multiples of 32
|
||||
reg [N-1:0] lfsr_reg[0:N/32-1];
|
||||
wire [N-1:0] lfsr_in[0:N/32-1];
|
||||
wire [N-1:0] taps_sel[0:N/32-1];
|
||||
wire [N/32-1:0] feedback;
|
||||
|
||||
// instantiate multiple 32bit rngs
|
||||
genvar i,j;
|
||||
generate
|
||||
for(i=0;i<(N/32);i=i+1) begin
|
||||
//taps
|
||||
assign taps_sel[i] = entaps ? taps[(i+1)*32-1:i*32]: 32'h80000057 << 1;
|
||||
//lfsr reg
|
||||
always @(posedge clk or negedge nreset)
|
||||
if(~nreset)
|
||||
lfsr_reg[i] <= seed[(i+1)*32-1:i*32];
|
||||
else if(en)
|
||||
lfsr_reg[i] <= lfsr_in[i];
|
||||
// feeback
|
||||
assign feedback[i] = lfsr_reg[i][31];
|
||||
assign lfsr_in[i][0] = feedback[i];
|
||||
for(j=1;j<32;j=j+1) begin
|
||||
assign lfsr_in[i][j] = taps_sel[i][j] ? (lfsr_reg[i][j-1] ^ feedback[i]) :
|
||||
lfsr_reg[i][j-1];
|
||||
|
||||
end
|
||||
assign out[(i+1)*32-1:i*32] = mask[(i+1)*32-1:i*32] & lfsr_reg[i];
|
||||
end // for (i=0;<N/32;i=i+1)
|
||||
endgenerate
|
||||
|
||||
|
||||
endmodule // oh_random
|
Loading…
x
Reference in New Issue
Block a user