EN 3542: Digital Systems Design Individual Project Report Pseudo Random Number Generator using Linear Feedback shift registers Index No: Name: 110445D I.W.A.S.U. Premaratne
1. Problem: Random numbers are useful in a wide variety of applications. There are basically two types of Random Number Generators, namely True Random Number Generators (TRNG) and Pseudo Random Number Generators (PRNG). True random number generators (TRNG) are slow and expensive while pseudo random number generators (PRNG) suffice for most applications. Although a majority of random number generators have been implemented in software level, increasing demand exists for hardware implementation due to the advent of faster and high density Field Programmable Gate Arrays (FPGA). Verilog language which is used to program FPGAs, also has a built in random Number generator but it can only be used in test benches. So, for a hardware design where random numbers are needed, such as encryption systems, we need a hardware implementation of a random number generator. 2. Solution: There are two main methods used to generate random numbers. Using a physical process: Measuring results of some physical phenomena which produces random results such as thermal noise and atmospheric noise generates true random numbers, since these are completely unpredictable. Using computational algorithms: Take an initial short value using which random results are generated. This method produces pseudo random numbers the algorithm might produce the same number sequence after a period of time. What matters is making that period as large as possible. Most pseudo random number generating algorithms, such as the most widely used PRNG - Mersenne twister method, involve complex mathematical operations which are not suitable to be implemented on hardware. Linear Feedback Shift Register based method is a less complex method that can be implemented in hardware. Hence the solution chosen was to implement a pseudo random number generator in hardware level using LFSRs. 3. Methodology: LFSR can be specified by means of a characteristic polynomial which is also called the feedback polynomial. Polynomial determines the width and the repeatability of random numbers. For most optimum solution feedback items (taps) should be selected such that maximum length sequence occurs. Maximum length sequence is the sequence of length 2 n 1 produced by n length registers. A LFSR is maximal length if an only if the following conditions are met. Number of taps should be even Set of taps taken altogether must be relatively prime.
For our convenience Xilinx has provided a table of appropriate taps for maximum length LFSR counters upto 168 bits, in their application note xapp052. Figure 1: Maximum length sequence generating LFSR
For a LFSR of 4 bits, Taps = 4, 3 Number of states = 2 4 1 = 15 Characteristic polynomial = x 4 + x 3 + 1 Figure 2: 4 Bit LFSR Here 1 is given as the initial value, from which the number sequence is initiated. 0001 1001 0101 1000 1100 1010 0011 0100 0110 1101 0111 0010 1011 1110 1111 Figure 3: State diagram of 4 bit LFSR For a number generator of 4 decimal digits, number of bits = 13 Therefore taps = 13, 4, 3, 1 Number of states = 2 13 1 = 8191 State diagram will have 8191 different states and is difficult to graphically represent. Characteristic polynomial = x 13 + x 4 + x 3 + 1 Figure 4: 13 bit LFSR
4. Simulation Results and Test bench Separate modules were used for LFSR and seven segment display. LFSR module is the top module. module lfsr( input clock, input reset, output a, output b, output c, output d, output e, output f, output g, output dp, output [3:0] an ); //------------Internal Variables-------- reg [12:0] out = 0; wire linear_feedback; //-------------XNOR each tap output with previous tap------- assign linear_feedback =! (!(!(out[12] ^ out[3])^out[2])^out[0]); reg [24:0] delay; //register to produce the delay in number generation wire test; always @ (posedge clock or posedge reset) begin if (reset) delay <= 0; else delay <= delay + 1; assign test = &delay; //AND each bit of delay with itself; test will be high only when //all bits of delay are high always @(posedge test or posedge reset) if (reset) begin // active high reset out <= 13'b0 ; else begin out <= {out[11],out[10], out[9],out[8], out[7],out[6], out[5],out[4], out[3],out[2], out[1],out[0],linear_feedback}; sseg S(.clock(clock),.reset(reset),.out(out),.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.dp(dp),.an(an)); module
module sseg( input clock, input reset, input [12:0] out, output a, output b, output c, output d, output e, output f, output g, output dp, output [3:0] an ); reg[3:0] ones, tens, hundreds, thousands=0; /*Binary to BCD conversion of state_out*/ // Internal variable reg [28:0] shift; integer i; always @(*) begin // Clear previous and store new number in shift register shift[28:13] = 0; shift[12:0] = out; // Loop eight times for (i=0; i<13; i=i+1) begin if (shift[16:13] >= 5) shift[16:13] = shift[16:13] + 3; if (shift[20:17] >= 5) shift[20:17] = shift[20:17] + 3; if (shift[24:21] >= 5) shift[24:21] = shift[24:21] + 3; if (shift[28:25] >= 5) shift[28:25] = shift[28:25] + 3; // Shift entire register left once shift = shift << 1; // Push decimal numbers to output thousands = shift[28:25]; hundreds = shift[24:21]; tens = shift[20:17]; ones = shift[16:13]; /*7 segment multiplexing*/ localparam N = 18; reg [N-1:0]count; always @ (posedge clock or posedge reset) begin if (reset) count <= 0; else count <= count + 1; reg [6:0]sseg; reg [3:0]an_temp; always @ (*) begin case(count[n-1:n-2]) 2'b00 : begin sseg = ones; an_temp = 4'b1110; 2'b01: begin sseg = tens; an_temp = 4'b1101; 2'b10: begin sseg = hundreds; an_temp = 4'b1011; 2'b11: begin sseg = thousands; an_temp = 4'b0111; case assign an = an_temp; reg [6:0] sseg_temp; always @ (*) begin case(sseg) 4'd0 : sseg_temp = 7'b1000000; //0 4'd1 : sseg_temp = 7'b1111001; //1 4'd2 : sseg_temp = 7'b0100100; //2 4'd3 : sseg_temp = 7'b0110000; //3 4'd4 : sseg_temp = 7'b0011001; //4 4'd5 : sseg_temp = 7'b0010010; //5 4'd6 : sseg_temp = 7'b0000010; //6 4'd7 : sseg_temp = 7'b1111000; //7 4'd8 : sseg_temp = 7'b0000000; //8 4'd9 : sseg_temp = 7'b0010000; //9 default : sseg_temp = 7'b0111111; //dash case assign {g, f, e, d, c, b, a} = sseg_temp; assign dp = 1'b1; module
Test bench: module lfsr_rng_test; // Inputs reg clock; reg reset; // Outputs wire a; wire b; wire c; wire d; wire e; wire f; wire g; wire dp; wire [3:0] an; // Instantiate the Unit Under Test (UUT) lfsr uut (.clock(clock),.reset(reset),.a(a),.b(b),.c(c),.d(d),.e(e),.f(f),.g(g),.dp(dp),.an(an) ); initial begin // Initialize Input clock = 0; reset = 0; #10 reset = 1; #10 reset = 0; always #10 clock =!clock; module
Clock and an register values change too fast. Delay register was shortened to 15 bits for simulation so that number generation will be faster than in hardware implementation, because if not, a limit on number of transitions that can be stored in waveform database (.wdb) file will be reached and waveform tracing will be stopped. Figure 5: Simulation window
4. Synthesized Circuit and Net list User constraints file (.ucf) contents # Pin assignment for pushbutton switches NET "reset" LOC = "a7"; # Pin assignment for 7-segment displays NET "a" LOC = "l14" ; NET "b" LOC = "h12" ; NET "c" LOC = "n14" ; NET "d" LOC = "n11" ; NET "e" LOC = "p12" ; NET "f" LOC = "l13" ; NET "g" LOC = "m12" ; NET "dp" LOC = "n13" ; NET "an<3>" LOC = "k14"; NET "an<2>" LOC = "m13"; NET "an<1>" LOC = "j12"; NET "an<0>" LOC = "f12"; # Pin assignment for clock NET "clock" LOC = "b8"; Figure 6: RTL schematic
Figure 7: Technology Schematic
Figure 10: Netlist
Figure 9: Project summary