diff options
-rw-r--r-- | A5.1/MyHDL/a5_homelien.py | 147 | ||||
-rw-r--r-- | A5.1/MyHDL/a5_homelien.v | 82 |
2 files changed, 229 insertions, 0 deletions
diff --git a/A5.1/MyHDL/a5_homelien.py b/A5.1/MyHDL/a5_homelien.py new file mode 100644 index 0000000..72aa8da --- /dev/null +++ b/A5.1/MyHDL/a5_homelien.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# v2, oystein@homelien.no, 2009 + +AVOID_CHAINING = True # hack + +SIMULATE = False +SIMULATE = True # comment out this line to generate verilog + +from myhdl import * + +def chain_xor(out, signals): + # build chain for taps (this is a typical myhdl hack..) + chain = [] + def xor(o, i1, i2, pos): + @always_comb + def c(): + o.next = i1 ^ i2[pos] + return c + inp = Signal(bool(0)) + for sig, pos in signals: + s = Signal(bool(0)) + x2 = xor(s, inp, sig, pos) + chain += [x2] + inp = s + + @always_comb + def output(): + out.next = s + + return chain, output + + +def lfsr_hw(clk, i, majority, length, taps, clockbit, name=""): + print "lfsr %s: len %s taps %s, clockbit %s" % (name, length, taps, clockbit) + + lfsr = Signal(intbv(0)[length:]) + + bit = Signal(bool(0)) + if not AVOID_CHAINING: + # this stopped working in some myhdl version. need to complain on the mailing list + chain = chain_xor(bit, [(i, 0)] + [(lfsr, tap) for tap in taps]); + else: + chain = () + + @always(clk.posedge) + def shift(): + if i[2]: + # reset + lfsr.next = 0 + elif i[1] or (majority == lfsr[clockbit]): # i[1] set if clocking forced (for init) + # calculate tap bits + lfsr.next = concat(lfsr[length-1:0], bit) + #print "shift, contents: %08x, bit %d" % (lfsr, bit) + + clockreg = Signal(bool(0)) + outputreg = Signal(bool(0)) + + @always_comb + def extract_bits(): + clockreg.next = lfsr[clockbit] + outputreg.next = lfsr[length-1] + + return (chain, shift, extract_bits), lfsr, clockreg, outputreg, bit + +def a5_homelien(clk, i, o): + """ + input[0] is initialization data + input[1] is True to force clocking (while initializing) + input[2] is reset (clocked, active high) + """ + + majority = Signal(bool(0)) + r1, r1_reg, r1_clk, r1_out, r1_bit = lfsr_hw(clk, i, majority, 19, [13, 16, 17, 18], 8, "R1") + r2, r2_reg, r2_clk, r2_out, r2_bit = lfsr_hw(clk, i, majority, 22, [20, 21], 10, "R2") + r3, r3_reg, r3_clk, r3_out, r3_bit = lfsr_hw(clk, i, majority, 23, [7, 20, 21, 22], 10, "R3") + @always_comb + def xors(): + # this should be done automatically with the chain function from the lists above + # but perhaps need to complain on myhdl list to get it working again + r1_bit.next = i[0] ^ r1_reg[13] ^ r1_reg[16] ^ r1_reg[17] ^ r1_reg[18] + r2_bit.next = i[0] ^ r2_reg[20] ^ r2_reg[21] + r3_bit.next = i[0] ^ r3_reg[7] ^ r3_reg[20] ^ r3_reg[21] ^ r3_reg[22] + + @always_comb + def calc_stuff(): + majority.next = (r1_clk + r2_clk + r3_clk) >= 2 + o.next = r1_out ^ r2_out ^ r3_out + + return (r1, r2, r3, calc_stuff, xors) + +def test(): + clk = Signal(bool(0)) + input = Signal(intbv(0)[3:]) # for initialization + output = Signal(bool(0)) + + algorithm = a5_homelien(clk, input, output) + + @instance + def test(): + key = 0xEFCDAB8967452312 #== 0x48C4A2E691D5B3F7 from A5/1 pedagogical implementation in C + fn = 0x000134 + known_good_AtoB = 0x14D3AA960BFA0546ADB861569CA30# == 0x534EAA582FE8151AB6E1855A728C00 from A5/1 pedagogical implementation in C + known_good_BtoA = 0x093F4D68D757ED949B4CBE41B7C6B#== 0x24FD35A35D5FB6526D32F906DF1AC0 from A5/1 pedagogical implementation in C + + phases = ( + ("clock in dummy key %s" % hex(key), 2, intbv(key)[64:]), + ("reset", 4, intbv(key)[1:]), + ("clock in key %s" % hex(key), 2, intbv(key)[64:]), + ("clock in fn %s" % hex(fn), 2, intbv(fn)[22:]), + ("100 fuzzing clocks", 0, intbv(0)[100:]), + ("A->B (expected: %s)" % hex(known_good_AtoB), 0, intbv(0)[114:]), + ("B->A (expected: %s)" % hex(known_good_BtoA), 0, intbv(0)[114:]), + ) + + for description, inputor, data in phases: + print "- %s" % description + result = intbv(0)[len(data):] + + for count in range(len(data)): + input.next = inputor + data[count] + + yield delay(10) + clk.next = not clk + yield delay(10) + clk.next = not clk + + #print "time %8d: r1 %08x r2 %08x r3 %08x maj %d input %x out %d%d%d" % (count, r1_reg, r2_reg, r3_reg, majority, input, r1_out, r2_out, r3_out) + count += 1 + + result = (result << 1) + output + print " result: %s" % hex(result) + + + return test, algorithm + +if SIMULATE: + Simulation(test()).run() +else: + clk = Signal(bool(0)) + input = Signal(intbv(0)[3:]) + output = Signal(bool(0)) + + toVerilog(a5_homelien, clk, input, output) + + print ".v file generated" + diff --git a/A5.1/MyHDL/a5_homelien.v b/A5.1/MyHDL/a5_homelien.v new file mode 100644 index 0000000..9e07a55 --- /dev/null +++ b/A5.1/MyHDL/a5_homelien.v @@ -0,0 +1,82 @@ +// File: a5_homelien.v +// Generated by MyHDL 0.6 +// Date: Sun Jan 18 02:22:21 2009 + +`timescale 1ns/10ps + +module a5_homelien ( + clk, + i, + o +); + +input clk; +input [2:0] i; +output o; +wire o; + +wire r1_out; +reg [18:0] r1_reg; +wire r1_bit; +wire r3_out; +wire r2_clk; +reg [21:0] r2_reg; +wire r3_bit; +wire majority; +wire r3_clk; +reg [22:0] r3_reg; +wire r2_bit; +wire r2_out; +wire r1_clk; + + + +always @(posedge clk) begin: A5_HOMELIEN_R1_1 + if (i[2]) begin + r1_reg <= 0; + end + else if ((i[1] || (majority == r1_reg[8]))) begin + r1_reg <= {r1_reg[(19 - 1)-1:0], r1_bit}; + end +end + + +assign r1_clk = r1_reg[8]; +assign r1_out = r1_reg[(19 - 1)]; + +always @(posedge clk) begin: A5_HOMELIEN_R2_1 + if (i[2]) begin + r2_reg <= 0; + end + else if ((i[1] || (majority == r2_reg[10]))) begin + r2_reg <= {r2_reg[(22 - 1)-1:0], r2_bit}; + end +end + + +assign r2_clk = r2_reg[10]; +assign r2_out = r2_reg[(22 - 1)]; + +always @(posedge clk) begin: A5_HOMELIEN_R3_1 + if (i[2]) begin + r3_reg <= 0; + end + else if ((i[1] || (majority == r3_reg[10]))) begin + r3_reg <= {r3_reg[(23 - 1)-1:0], r3_bit}; + end +end + + +assign r3_clk = r3_reg[10]; +assign r3_out = r3_reg[(23 - 1)]; + + +assign majority = (((r1_clk + r2_clk) + r3_clk) >= 2); +assign o = (r1_out ^ r2_out ^ r3_out); + + +assign r1_bit = (i[0] ^ r1_reg[13] ^ r1_reg[16] ^ r1_reg[17] ^ r1_reg[18]); +assign r2_bit = (i[0] ^ r2_reg[20] ^ r2_reg[21]); +assign r3_bit = (i[0] ^ r3_reg[7] ^ r3_reg[20] ^ r3_reg[21] ^ r3_reg[22]); + +endmodule |