/* permsums: Coded by Antti Karttunen, Jan 30-31 & Jun 21-... 2005. (Continued 27. February 2006.) Continued 1. October 2007. Generate all permutations of the set {1..n} for successive n's 1, 2, 3, ..., 18, and collect the minimum and maximum of the sum p(1)*p(2) + p(2)*p(3) + p(3)*p(4) +... + p(n-1)*p(n) + p(n)*p(1). and show them on the 4x7-segment display. The meaning of the slide switches: SW_IN[0] & SW_IN[1] (the rightmost) (the second rightmost) DOWN DOWN --> Show the four most significant digits of current fex. UP DOWN --> Show the four rightmost elements of current perm. DOWN UP --> Show the current psum in hexadecimal. UP UP --> Show the current maxsum in hexadecimal. The four decimal point leds will show the four least significant bits of n. The five rightmost leds will show the binary expansion of the fifth rightmost element of the permutation. */ module permsums(CLK,PB_IN,SW_IN,SEG_OUT,DIGIT_OUT,LED_OUT); input CLK; input [2:0] PB_IN; input [2:0] SW_IN; output [7:0] SEG_OUT; output [3:0] DIGIT_OUT; output [7:0] LED_OUT; // n starts from 2, grows up to 18. reg [4:0] n = 0; // (2-18). reg [4:0] nplus1 = 1; // (3-19). // reg [4:0] n = 2; // (2-18). // reg [4:0] nplus1 = 3; // (3-19). // Wires out of the 17-digit factorial expansion incrementer: // (Range from 00000000000000000 to HGFEDCBA987654321, where H=17, G=16, F=15, etc.) wire f1; wire [1:0] f2; wire [1:0] f3; wire [2:0] f4; wire [2:0] f5; wire [2:0] f6; wire [2:0] f7; wire [3:0] f8; wire [3:0] f9; wire [3:0] f10; wire [3:0] f11; wire [3:0] f12; wire [3:0] f13; wire [3:0] f14; wire [3:0] f15; wire [4:0] f16; wire [4:0] f17; wire [4:0] wp [17:0]; // Wires out of permutation engine. // The sum of such permutation computed in cyclical Quet-Deutsch manner. wire [13:0] wpsum; wire [13:0] wminsum; wire [13:0] wmaxsum; /**********************************************************************/ /* */ /* HALVE THE CLOCK FREQUENCY */ /* */ /**********************************************************************/ wire GND = 1'b0; wire CLK_USED; wire CLK_LOCKED; wire CLK0; puolita PUOLITAS(.CLKIN_IN(CLK), .RST_IN(GND), .CLKDV_OUT(CLK_USED), .CLKIN_IBUFG_OUT(), .CLK0_OUT(CLK0), .LOCKED_OUT(CLK_LOCKED)); /**********************************************************************/ reg enable_permeng = 0; wire out_perm_valid; reg prev_perm_valid_state = 0; wire perms_just_finished = (~out_perm_valid && prev_perm_valid_state); wire out_sums_valid; reg prev_pipe_endpoint_state = 0; wire pipe_just_finished = (~out_sums_valid && prev_pipe_endpoint_state); wire PB_IN0; // State of the debounced push button for incrementing. reg pb_in0_prev = 0; // is saved here also. debounced_button DBB0(CLK_USED,PB_IN[0],PB_IN0); wire pb_in0_pressed = (PB_IN0 && ~pb_in0_prev); wire PB_IN1; // State of the debounced push button for incrementing. reg pb_in1_prev = 1; // is saved here also. debounced_button DBB1(CLK_USED,PB_IN[1],PB_IN1); wire single_step = SW_IN[2]; // We compute the next permutation, either when PB0 is pressed, // or always when single_step switch is not on: wire compute_next_permutation = (pb_in0_pressed || !single_step); /**********************************************************************/ /* */ /* LED-displays for debugging */ /* */ /**********************************************************************/ // fexmsb1 is the most significant digit of the factorial expansion, // fexmsb4 is the fourthmost significant digit. wire [4:0] fexmsb1 = ((n < 6) ? {2'b00,f4} : (6 == n) ? {2'b00,f5} : (7 == n) ? {2'b00,f6} : (8 == n) ? {2'b00,f7} : (9 == n) ? {1'b0,f8} : (10 == n) ? {1'b0,f9} : (11 == n) ? {1'b0,f10} : (12 == n) ? {1'b0,f11} : (13 == n) ? {1'b0,f12} : (14 == n) ? {1'b0,f13} : (15 == n) ? {1'b0,f14} : (16 == n) ? {1'b0,f15} : (17 == n) ? f16 : f17); wire [4:0] fexmsb2 = ((n < 6) ? {3'b000,f3} : (6 == n) ? {2'b00,f4} : (7 == n) ? {2'b00,f5} : (8 == n) ? {2'b00,f6} : (9 == n) ? {2'b00,f7} : (10 == n) ? {1'b0,f8} : (11 == n) ? {1'b0,f9} : (12 == n) ? {1'b0,f10} : (13 == n) ? {1'b0,f11} : (14 == n) ? {1'b0,f12} : (15 == n) ? {1'b0,f13} : (16 == n) ? {1'b0,f14} : (17 == n) ? {1'b0,f15} : f16); wire [4:0] fexmsb3 = ((n < 6) ? {3'b000,f2} : (6 == n) ? {3'b000,f3} : (7 == n) ? {2'b00,f4} : (8 == n) ? {2'b00,f5} : (9 == n) ? {2'b00,f6} : (10 == n) ? {2'b00,f7} : (11 == n) ? {1'b0,f8} : (12 == n) ? {1'b0,f9} : (13 == n) ? {1'b0,f10} : (14 == n) ? {1'b0,f11} : (15 == n) ? {1'b0,f12} : (16 == n) ? {1'b0,f13} : (17 == n) ? {1'b0,f14} : {1'b0,f15}); wire [4:0] fexmsb4 = ((n < 6) ? {4'b0000,f1} : (6 == n) ? {3'b000,f2} : (7 == n) ? {3'b000,f3} : (8 == n) ? {2'b00,f4} : (9 == n) ? {2'b00,f5} : (10 == n) ? {2'b00,f6} : (11 == n) ? {2'b00,f7} : (12 == n) ? {1'b0,f8} : (13 == n) ? {1'b0,f9} : (14 == n) ? {1'b0,f10} : (15 == n) ? {1'b0,f11} : (16 == n) ? {1'b0,f12} : (17 == n) ? {1'b0,f13} : {1'b0,f14}); shw5spec DIGDISPLAY(CLK_USED, /* p[3],p[2],p[1],p[0], */ (SW_IN[0] ? (SW_IN[1] ? {2'b00,wmaxsum[13:12]} : wp[3]) : (SW_IN[1] ? {2'b00,wpsum[13:12]} : fexmsb1)), (SW_IN[0] ? (SW_IN[1] ? wmaxsum[11:8] : wp[2]) : (SW_IN[1] ? wpsum[11:8] : fexmsb2)), (SW_IN[0] ? (SW_IN[1] ? wmaxsum[7:4] : wp[1]) : (SW_IN[1] ? wpsum[7:4] : fexmsb3)), (SW_IN[0] ? (SW_IN[1] ? wmaxsum[3:0] : wp[0]) : (SW_IN[1] ? wpsum[3:0] : fexmsb4)), // 1'b1,1'b1,1'b1,1'b1, ~(n[3]),~(n[2]),~(n[1]),~(n[0]), SEG_OUT,DIGIT_OUT); assign LED_OUT = {out_sums_valid,out_perm_valid,enable_permeng,wp[4]}; /**********************************************************************/ /* */ /* Instantiate Permutation Engine and Sum & Compare modules */ /* */ /**********************************************************************/ perm17eng PERMENG(CLK_USED, (enable_permeng && !perms_just_finished), n, nplus1, out_perm_valid, f1,f2,f3,f4,f5,f6,f7,f8,f9,f10, f11,f12,f13,f14,f15,f16,f17, wp[0],wp[1],wp[2],wp[3],wp[4],wp[5],wp[6],wp[7],wp[8],wp[9], wp[10],wp[11],wp[12],wp[13],wp[14],wp[15],wp[16],wp[17] ); sum19cmp SUMCMP(CLK_USED, out_perm_valid, n, nplus1, wp[0],wp[1],wp[2],wp[3],wp[4],wp[5],wp[6],wp[7],wp[8],wp[9], wp[10],wp[11],wp[12],wp[13],wp[14],wp[15],wp[16],wp[17], out_sums_valid, wminsum, wmaxsum, wpsum ); /**********************************************************************/ always @(posedge CLK_USED) begin if(perms_just_finished) enable_permeng <= 0; pb_in0_prev <= PB_IN0; pb_in1_prev <= PB_IN1; prev_perm_valid_state <= out_perm_valid; prev_pipe_endpoint_state <= out_sums_valid; if(compute_next_permutation) begin if(pipe_just_finished) begin n <= nplus1; nplus1 <= nplus1+1; enable_permeng <= 1; end else if(~|n) begin n <= 2; nplus1 <= 3; enable_permeng <= 1; end end end endmodule