// this code derived from from http://www-inst.eecs.berkeley.edu/~barrel/rc5test.c //#define ROTL(A,B) (SHL((A),(B))|SHR((A),(32-(B)))) //#define SHL(A,B) ((A)<<(B)) //#define SHR(A,B) ((A)>>(B)) //#define ROTL3(A) (ROTL((A),3)) module solve4(clk, reset0, rw0, ad0, data0, ack0, last0, reset12, rw1, ad1, data1, ack1, last1, rw2, ad2, data2, ack2, last2); input clk; // system clock input reset0; input rw0; // write strobe input ad0; // address/data output ack0; reg ack0; output last0; // we're at the end inout [ 7: 0]data0; // // output bus 1 // inout [ 7: 0]data1; output reset12; output rw1; // write strobe output ad1; // address/data input ack1; input last1; // // output bus 2 // inout [ 7: 0]data2; output rw2; // write strobe output ad2; // address/data input ack2; input last2; // // here's the main state machine // // for what the variables mean check out the C // version // reg [31: 0]magic1, c_magic1; reg [31: 0]A0, c_A0; reg [31: 0]B0, c_B0; reg [31: 0]AB1, c_AB1, tmp; reg [31: 0]BL1, c_BL1; reg [31: 0]A2, c_A2; reg [31: 0]BL2, c_BL2; reg [31: 0]A3, c_A3; reg [31: 0]p1, c_p1; reg [31: 0]p2, c_p2; reg [31: 0]p3, c_p3; reg [31: 0]C3, c_C3; reg [31: 0]p4, c_p4; reg [31: 0]p5, c_p5; reg [31: 0]p6, c_p6; reg [31: 0]p7, c_p7; reg [31: 0]p0, c_p0; reg [31: 0]L1, c_L1; reg [31: 0]L2, c_L2; reg [31: 0]L3, c_L3; reg [31: 0]L4, c_L4; reg [ 4: 0]B1i, c_B1i; reg [ 4: 0]B2i, c_B2i; reg [ 6: 0]indr3, c_indr3; // sram read address reg [ 6: 0]indw2, c_indw2, ii; // sram write address reg [ 4: 0]i, c_i; // counter for state machine reg [ 4: 0]xind3, c_xind3; reg [ 1: 0]beat, c_beat; // phase (for the 4 keys running at any one time) reg [ 3: 0]state, c_state; // one-hot state variable - we spend // 1 set of 4 clocks in state[0] initialising // 26 sets of 4 clocks in state[1] // 26 sets of 4 clocks in state[2] // 26 sets of 4 clocks in state[3] reg finished; // last key in block reg done; // signal completion reg testend; // sampling period for keys reg found; // signal success reg [ 2: 0]addr; // register address register reg run; // start/stop control - when asserted we go to start state reg ack; // ack out reg [ 1: 0]scnt; // write strobe count reg [ 7: 0]dataout; // output data wires reg lastrw, rwx; // write strobe MS flops reg [31:28]key1_done; // end of block indicator register reg [31: 2]key1; // block counter reg [31: 0]key0; // 32 MSBs of key reg reset_down; // internal reset state reg enable1, enable2; // enables for the two output buses wire last0 = (enable1|enable2); // true if we're the target // // register strobes // wire astrobe = ad0&(scnt==1); // address register write wire dstrobe0 = ~ad0&(scnt==1); // general reset write wire dstrobe = ~ad0&(scnt==1)&!last0; // normal register strobe wire dstrobel = ~ad0&(scnt==1)&((enable1&!last1)|(enable2&!last2)); // next up register strobe // // external down bus control logic // assign reset12 = reset_down; always @(posedge clk) reset_down = #1 (reset0 ? 1: dstrobe0 && (addr == 0) && data0[0] ? data0[1] : dstrobe && (addr == 0) && data0[2] ? 0 : reset_down); // // enable registers for down buses // always @(posedge clk) enable1 = #1(reset_down?0 : dstrobe && (addr==1) ? ~data0[1]&(enable1|data0[5]) : dstrobel && (addr==2) ? ~data0[1]&enable1 : enable1); always @(posedge clk) enable2 = #1(reset_down?0 : dstrobe && (addr==1) ? ~data0[2]&(enable2|data0[6]) : dstrobel && (addr==2) ? ~data0[2]&enable2 : enable2); assign rw1 = rw0&enable1; assign rw2 = rw0&enable2; assign ad1 = ad0; assign ad2 = ad0; assign data1 = (rw0 ? data0 : 8'hz); assign data2 = (rw0 ? data0 : 8'hz); // // register space // // 0 global reset // // 2:2 local clear reset // 1:1 reset value // 0:0 global set reset to bit 1 // // 1 start // // 6:6 set enable bus 2 // 5:5 set enable bus 1 // 4:4 set run // 2:2 clear enable bus 2 // 1:1 clear enable bus 1 // 0:0 clear run // // 2 start (last) // // 6:6 set enable bus 2 // 5:5 set enable bus 1 // 4:4 set run // 2:2 clear enable bus 2 // 1:1 clear enable bus 1 // 0:0 clear run // // 3 key1 // 7:4 start high 31:28 // 3:0 end high 31:28 // // 4 key0[31:24] // // 5 key0[23:16] // // 6 key0[15: 8] // // 7 key0[ 7: 0] // assign data0 = (rw0 ? 8'hz : dataout); // // acknowledge writes // always @(posedge clk) ack = #1 (reset0?0 : scnt == 1 ? ~ack:ack); // // wait for data to settle // always @(posedge clk) scnt = #1 (reset0?0 : rwx && !lastrw ? 3 : scnt != 0 ? scnt-1 : 0); always @(posedge clk) rwx = #1 rw0; always @(posedge clk) lastrw = #1 rwx; // // address register // always @(posedge clk) addr = #1 (astrobe ? data0[2:0] : addr); //WORD L[2] = {0x9f1be582, 0xf918c79c}; //WORD PIV[2] = {0xd85ccd8d, 0xaa7416b4}; //iv[0] ^ plain[0] = PIV[0] = 0xf839a5d9 ^ 0x20656854 = 0xd85ccd8d //iv[1] ^ plain[1] = PIV[1] = 0xc41f78c1 ^ 0x6e6b6e75 = 0xaa7416b4 //unsigned int iv[2] = {0xf839a5d9, 0xc41f78c1 }; //d9 a5 39 f8 c1 78 1f c4 //unsigned int plain[2] = {0x20656854, 0x6e6b6e75 }; //54 68 65 20 75 6e 6b 6e //wire [31:0]PIV0 = 32'hd5d5ce79 ^ 32'h20656854; // for real //wire [31:0]PIV1 = 32'hfcea7550 ^ 32'h6e6b6e75; wire [31:0]PIV0 = 32'hf839a5d9 ^ 32'h20656854; // practice wire [31:0]PIV1 = 32'hc41f78c1 ^ 32'h6e6b6e75; wire [31:0]res0=32'hb74be041; wire [31:0]res1=32'h496def29; //wire [31:0]key0 = 32'h9f1be582; // for practice wire [31:0]key1_init = 32'hf918c79c; // for practice //wire [31:0]key1_init = 32'h00000000; // for real run time //wire [31:0]key1_init = 32'hffffff00; // for checking correct completion // // 32-bit barrel shifter/rotator // function [31:0]ROTL; input [31:0]a; input [4:0]b; case (b) 0: ROTL = a; 1: ROTL = {a[30:0],a[31]}; 2: ROTL = {a[29:0],a[31:30]}; 3: ROTL = {a[28:0],a[31:29]}; 4: ROTL = {a[27:0],a[31:28]}; 5: ROTL = {a[26:0],a[31:27]}; 6: ROTL = {a[25:0],a[31:26]}; 7: ROTL = {a[24:0],a[31:25]}; 8: ROTL = {a[23:0],a[31:24]}; 9: ROTL = {a[22:0],a[31:23]}; 10: ROTL = {a[21:0],a[31:22]}; 11: ROTL = {a[20:0],a[31:21]}; 12: ROTL = {a[19:0],a[31:20]}; 13: ROTL = {a[18:0],a[31:19]}; 14: ROTL = {a[17:0],a[31:18]}; 15: ROTL = {a[16:0],a[31:17]}; 16: ROTL = {a[15:0],a[31:16]}; 17: ROTL = {a[14:0],a[31:15]}; 18: ROTL = {a[13:0],a[31:14]}; 19: ROTL = {a[12:0],a[31:13]}; 20: ROTL = {a[11:0],a[31:12]}; 21: ROTL = {a[10:0],a[31:11]}; 22: ROTL = {a[9:0],a[31:10]}; 23: ROTL = {a[8:0],a[31:9]}; 24: ROTL = {a[7:0],a[31:8]}; 25: ROTL = {a[6:0],a[31:7]}; 26: ROTL = {a[5:0],a[31:6]}; 27: ROTL = {a[4:0],a[31:5]}; 28: ROTL = {a[3:0],a[31:4]}; 29: ROTL = {a[2:0],a[31:3]}; 30: ROTL = {a[1:0],a[31:2]}; 31: ROTL = {a[0],a[31:1]}; endcase endfunction wire [31:0]P = 32'hb7e15163; wire [31:0]Q = 32'h9e3779b9; // // sram model (the altera parts contain srams that are piped this way) // reg [31: 0]rmem0; // memory output buffer reg [31: 0]mem[0:103]; // temp memory always @(posedge clk) rmem0 = #1 mem[indr3]; always @(posedge clk) begin ii = indw2; mem[ii] = #1 A2; end // // start sequence - asserting this holds the state machine ready to go // always @(posedge clk) run = #1 (reset_down? 0 : dstrobe & (addr == 1) ? ~data0[0]&(run|data0[4]) : run); // // per-key sequencing // wire count = state[2]&&i==0&&beat==0; // increment the key counter always @(posedge clk) key1_done = #1 (dstrobe&(addr==3)?data0[3:0]:key1_done); always @(posedge clk) key1 = #1 (dstrobe&(addr==3)?{data0[7:4], key1_init[27:2]}: count?key1+1:key1); always @(posedge clk) key0 = #1 {dstrobe&(addr==4)?data0[7:0]:key0[31:24], dstrobe&(addr==5)?data0[7:0]:key0[23:16], dstrobe&(addr==6)?data0[7:0]:key0[15: 8], dstrobe&(addr==7)?data0[7:0]:key0[ 7: 0]}; // // set this when the key1 register overflows // always @(posedge clk) finished = #1 (!run ? 0 : count && key1[27:2]==26'h3ffffff && key1[31:28]==key1_done ? 1 : finished); // // set this for the 4 beats when valid keys are being produced // always @(posedge clk) testend = #1 (!run?0 : state[3] && beat==3 && i==25 ? 1 : state[0] && beat==3 ? 0 : testend); // // true if we found a match (pass go, collect $10,000) // wire pass = testend && (p0==res0 && p4==res1); // test against the plain text // // remember we found it // always @(posedge clk) found = #1 (!run ? 0: pass|found); // // remember we're done // always @(posedge clk) done = #1 (!run ? 0: pass|done|(state[0] && finished)); // // output mux // always @(key1 or addr or run or pass or data1 or data2 or enable1 or enable2 or ack1 or ack or ack2) if (enable1) begin dataout = data1; ack0 = ack1; end else if (enable2) begin dataout = data2; ack0 = ack2; end else begin ack0 = ack; if (addr[0]) begin dataout = key1[31:24]; end else begin dataout = {key1[23:18],found, done}; end end // synopsys translate_off //`ifdef MAC initial $gr_waves("rw0",rw0,"dstrobe",dstrobe,"addr",addr,"enable1",enable1,"enable2",enable2,"reset0",reset0,"reset_down",reset_down,"dstrobe0",dstrobe0,"scnt",scnt,"run",run,"beat",beat,"state", state, "i",i,"indr3",indr3,"rmem0",rmem0,"indw2",indw2,"A0",A0, "B0",B0, "L4",L4, "p0", p0,"p4",p4,"AB1",AB1, "BL1",BL1,"magic1",magic1,"A2",A2, "BL2",BL2,"A3",A3, "L1",L1, "testend", testend, "pass",pass,"found",found,"done",done); //`else //initial $recordvars; //`endif // synopsys translate_on // // main state machine and data path // always @(state or beat or magic1 or indr3 or indw2 or A0 or B0 or p0 or PIV0 or rmem0 or i or A3 or AB1 or p1 or A2 or B1i or B2i or p2 or PIV1 or p3 or p4 or P or Q or p5 or p6 or p7 or L1 or L2 or L3 or L4 or BL1 or BL2 or key0 or key1 or C3 or xind3 or run) begin c_AB1 = A0+B0; c_B1i = B0[4:0]; c_BL1 = L4+B0; c_magic1 = (state[1] && i == 0 ? P : state[1] ? (beat == 0 ? magic1 + Q : magic1): rmem0); // get the head of the fifo c_p1 = p0^p4; c_L1 = (state[0]?key0:state[1] && i == 0?{key1[31:2], beat}:B0); c_p5 = p4; tmp = magic1 + AB1; // first c_indw2 = (i == 0 && beat == 1 ? 0 : indw2+1); c_A2 = {tmp[28:0], tmp[31:29]}; // ROT3 to make A c_BL2 = BL1; c_B2i = B1i; c_p2 = ROTL(p1, p5[4:0]); c_L2 = L1; c_p6 = p5; c_C3 = A2+BL2; c_xind3 = A2[4:0]+B2i; c_A3 = A2; c_L3 = L2; c_p3 = ( beat==2 && i == 0 ? PIV0: beat==2 && i == 1 ? PIV1 : p2); c_p7 = p6; c_indr3 = (i == 25 && beat == 2 ? 0 : indr3+1); c_A0 = (state[0]|(state[1]&(i==0)&(beat!=3))?0:A3); c_B0 = (state[0]|(state[1]&(i==0)&(beat!=3))?0:ROTL(C3, xind3)); c_L4 = L3; c_p4 = A3 + p3; c_p0 = p7; c_beat = beat+1; if (beat != 3) begin c_i = i; c_state = state; end else if (state[0] || i == 25) begin // every 26 beats switch to a new phase c_i = 0; c_state = {state[3:0],1'b0}; end else begin c_i = i+1; c_state = state; end if (!run || (state[3] && i==25 && beat == 3) || done) begin c_beat = 0; c_state = 1; end end always @(posedge clk) magic1 = #1 c_magic1; always @(posedge clk) A0 = #1 c_A0; always @(posedge clk) B0 = #1 c_B0; always @(posedge clk) AB1 = #1 c_AB1; always @(posedge clk) BL1 = #1 c_BL1; always @(posedge clk) BL2 = #1 c_BL2; always @(posedge clk) p1 = #1 c_p1; always @(posedge clk) A2 = #1 c_A2; always @(posedge clk) A3 = #1 c_A3; always @(posedge clk) p2 = #1 c_p2; always @(posedge clk) p3 = #1 c_p3; always @(posedge clk) C3 = #1 c_C3; always @(posedge clk) p4 = #1 c_p4; always @(posedge clk) p5 = #1 c_p5; always @(posedge clk) p6 = #1 c_p6; always @(posedge clk) p7 = #1 c_p7; always @(posedge clk) p0 = #1 c_p0; always @(posedge clk) L1 = #1 c_L1; always @(posedge clk) L2 = #1 c_L2; always @(posedge clk) L3 = #1 c_L3; always @(posedge clk) L4 = #1 c_L4; always @(posedge clk) B1i = #1 c_B1i; always @(posedge clk) B2i = #1 c_B2i; always @(posedge clk) indr3 = #1 c_indr3; always @(posedge clk) indw2 = #1 c_indw2; always @(posedge clk) i = #1 c_i; always @(posedge clk) xind3 = #1 c_xind3; always @(posedge clk) beat = #1 c_beat; always @(posedge clk) state = #1 c_state; endmodule