A5/1 Circuit, expressed in Verilog

The following is equivalent to the purported A5/1 
pedagogical C earlier published.

For non-commercial, non-governmental use only.

It comes with a testbench and sample output.

/*
a5.v
Purported A5/1 circuit, expressed in Verilog. 
13 May 99 
David Honig
honig@sprynet.com

Derived from Briceno, Goldberg, Wagner's Pedagogical C Code
of May 99.

To load key: assert Startloading, load data starting on next clock,
bitwise (1 delay + 64 key + 22 frame clocks).

Then wait for Doneloading to be asserted (100 more clocks).  Then
harvest your bits.

A testbench and sample output is appended as comments.

This synthesizes to about 150 LCs and runs at 80 Mhz on
the smaller Altera CPLDs e.g., 10K30.

*/



module a5(Clk, Reset_n,
        Bitout,
        Keybit,
        Startloading,
        Doneloading);


input Clk, Reset_n;
output Bitout;          // output keystream
        reg Bitout;
input   Keybit;         // input keybits 64 + 22
input   Startloading;   // initial keyload
output  Doneloading;    // signal done of keyloading
        reg Doneloading;


// internal state; lsb is leftmost 
reg [18:0] lfsr_1;
reg [21:0] lfsr_2;
reg [22:0] lfsr_3;

reg [1:0] State;        // FSM control
reg [6:0] Counter;      // for counting steps
reg [2:0] Phase;        // for sequencing phases

wire hi_1, hi_2, hi_3;
assign hi_1 = lfsr_1[18];
assign hi_2 = lfsr_2[21];
assign hi_3 = lfsr_3[22];


wire mid1, mid2, mid3;
assign mid1=lfsr_1[8];  
assign mid2=lfsr_2[10];  
assign mid3=lfsr_3[10];  


wire maj; 
assign maj=majority(mid1, mid2, mid3);

wire newbit1, newbit2, newbit3;
assign newbit1= ( lfsr_1[13] ^ lfsr_1[16] ^ lfsr_1[17] ^ lfsr_1[18] );
assign newbit2= ( lfsr_2[20] ^ lfsr_2[21] ) ;
assign newbit3= ( lfsr_3[7]  ^ lfsr_3[20] ^ lfsr_3[21] ^ lfsr_3[22] );


parameter IDLE=0;
parameter KEYING=1;
parameter RUNNING=2;


always @(posedge Clk or negedge Reset_n) begin
if (!Reset_n) begin: resetting

        $display("a5 reset");
        Doneloading <=0;
        Bitout <=0;
        {lfsr_1, lfsr_2, lfsr_3} <= 64'h 0;
        {State, Counter, Phase} <=0;

        end // reset
else begin
        case (State)

           IDLE: begin: reset_but_no_key

                if (Startloading) begin: startloadingkey
                        // $display("Loading key starts at %0d ", $time);
                        State <= KEYING; 
                        {lfsr_1, lfsr_2, lfsr_3} <= 64'h 0;
                        Phase <=0; Counter<=0;
                        end // if
                end // idle

           KEYING: begin

                case (Phase) 

                        0: begin: load64andclock
                        
                                clockallwithkey;

                                // $display("Loading key bit %0b  %0d at %0d   %0x", Keybit, Counter, $time, lfsr_1);
                                if (Counter==63) begin
                                        Counter <=0; 
                                        Phase <= Phase +1; 
                                        $display(" ");

                                        end
                                else Counter <=Counter+1; 
                                end

                        1: begin: load22andclock

                                // $display("Loading frame bit %0b at %0d %0d   %0x", Keybit, Counter, $time, lfsr_1);
                                clockallwithkey;

                                if (Counter==21) begin
                                        Counter <=0; 
                                        Phase <= Phase +1; 
                                        end
                                else Counter <=Counter+1;  
                                end

                        2: begin: clock100

                                majclock;

                                if (Counter ==100) begin
                                        $display("Done keying, now running %0d\n", $time);
                                        State <= RUNNING; 
                                        end
                                else Counter <= Counter+1; 
                                end
                endcase // Phase
                end // keying

           RUNNING: begin

                Doneloading <=1;        // when done loading
                Bitout <= hi_1 ^ hi_2 ^ hi_3; 
                majclock;

                end // running
        endcase // State
        end // else not resetting
end // always











function majority;
input a,b,c;

begin
        case({a,b,c}) // synopsys parallel_case
          3'b 000: majority=0;
          3'b 001: majority=0;
          3'b 010: majority=0;
          3'b 011: majority=1;

          3'b 100: majority=0;
          3'b 101: majority=1;
          3'b 110: majority=1;
          3'b 111: majority=1;
        endcase
end
endfunction


task clock1;
begin
        lfsr_1 <= ( lfsr_1 << 1 ) | newbit1; 
end
endtask

task clock2;
begin
        lfsr_2 <= (lfsr_2 << 1) | newbit2; 
end
endtask

task clock3;
begin
        lfsr_3 <= (lfsr_3 << 1) | newbit3; 
end
endtask

task clockall;
begin
        clock1;
        clock2; 
        clock3;
end
endtask

task clockallwithkey;
begin
        lfsr_1 <= ( lfsr_1 << 1 ) |  newbit1 ^ Keybit; 
        lfsr_2 <= ( lfsr_2 << 1 ) |  newbit2 ^ Keybit; 
        lfsr_3 <= ( lfsr_3 << 1 ) |  newbit3 ^ Keybit; 
end
endtask

task majclock;
begin
        if (mid1 == maj) clock1;
        if (mid2 == maj) clock2;
        if (mid3 == maj) clock3;
end
endtask


endmodule














/**************** CUT HERE FOR TESTBENCH test_a5.v **************************

module test_a5;


reg Clk, Reset_n;
wire Bitout;            // output keystream

reg     Keybit;         // input keybits 64 + 22
reg     Startloading;   // initial keyload
wire    Doneloading;    // signal done of keyloading


reg [0:7] key [7:0]; 
reg [22:0] frame; 



a5 dut(Clk, Reset_n,
        Bitout,
        Keybit,
        Startloading,
        Doneloading);


always @(Clk) #5 Clk <= ~Clk;

integer i,j;


initial begin
        #5
        key[0]= 8'h 12;
        key[1]= 8'h 23;
        key[2]= 8'h 45;
        key[3]= 8'h 67;

        key[4]= 8'h 89;
        key[5]= 8'h AB;
        key[6]= 8'h CD; 
        key[7]= 8'h EF;

        frame <= 22'h 134;
        Clk <=0;
        Reset_n <=1; 
        Startloading <=0;
        Keybit <=0;
        
        #10 Reset_n <=0; 
        #10 Reset_n <=1; 

        // key setup 
        
        #100
         Startloading <=1; $display("Starting to key %0d", $time); 
        for (i=0; i<8; i=i+1) begin
                for (j=0; j<8; j=j+1) begin
                        #10 Startloading <=0; 
                            Keybit <= key[i] >> j;
                        end // j
                end // i

        for (i=0; i<22; i=i+1) begin
                #10 Keybit <= frame[i]; 
                end

        wait(Doneloading); $display("Done keying %0d", $time); 

        $write("\nBits out: \n"); 
        repeat (32) #10 $write("%b", Bitout);


        $display("\nknown good=\n%b", 32'h 534EAA58);
        
        #1000 $display("\nSim done."); $finish;
end // init 

endmodule



************************* END OF TESTBENCH ************************************/


/**** SAMPLE OUTPUT
 
a5 reset
a5 reset
Starting to key 125
 
Done keying, now running 2000

Done keying 2010

Bits out: 
01010011010011101010101001011000
known good=
01010011010011101010101001011000

Sim done.
*********/


// eof