// m8266_ucode // // pdp11/34a microcode system. // Module is M8266 // see "1134A Field Maintenance Print Set (Jan 1977, MP00190).pdf" // sheets K2-7 ,-8, -9, -10// // // this module // - accesses the primary micro store 512x 48 bit made from 12 roms // - splits the primary code store into fields // - expands some fields with secondary ROMs // - displays the final fields /* unexpanded fields directly from primary code store E110.11 00 MPC08 E110.12 01 MPC07 E110.13 02 MPC06 E110.14 03 MPC05 E109.11 04 MPC04 E109.12 05 MPC03 E109.13 06 MPC02 E109.14 07 MPC01 E108.11 08 MPC00 E108.12 09 MISC CONTROL.0 1=K2-7 LOAD IRL, 2=LOAD PSW L, 3=LOAD CC L, E108.13 10 MISC CONTROL.1 4=BUT DEST L, 5=ENAB STOV L, E108.14 11 MISC CONTROL.2 6=LAOD COUNT L, 7=CLK COUNT L E107.11 12 BUF DAT TRAN H E107.12 13 BUF C1 H E107.13 14 BUF C0 H E107.14 15 ENAB MAINT H E106.11 16 LOAD BA H E106.12 17 LONG CYCLE L E106.13 18 AUX CONTROL E106.14 19 ALU TO ROM E82 E99.11 20 ALU FUNC CODE 03 H E99.12 21 ALU FUNC CODE 02 H E99.13 22 ALU FUNC CODE 01 H E99.14 23 ALU FUNC CODE 00 H E97.11 24 B E97.12 25 BX E97.13 26 OVX E97.14 27 DBE E98.14 28 SSMUX CONTROL SS01 E98.13 29 SSMUX CONTROL SS00 E98.12 30 AMUX CONTROL AMUX S1 E98.11 31 AMUX CONTROL AMUX S0 E100.11 32 BUT BIT 0 E100.12 33 BUT BIT 1 E100.13 34 BUT BIT 2 E100.14 35 BUT BIT 3 E104.11 36 SPA SRC SEL 1 E104.12 37 SPA SRC SEL 0 E104.13 38 SPA DEST SEL 1 E104.14 39 SPA DEST SEL 0 E103.11 40 FORCE RSVI L E103.12 41 PREVIOUS MODE L E103.13 42 BUT SERVICE H E103.14 43 FORCE KERNEL H E105.11 44 ROM SPA 03 E105.12 45 ROM SPA 02 E105.13 46 ROM SPA 01 E105.14 47 ROM SPA 00 */ // output: print module m8266_ucode() ; reg [8:0] mpc ; // micro program counter is 9 bit /*** the different micro code fields ***/ wire [47:0] ustore_primary_q ; // primary ustore data // fields wire [8:0] mpc_next ; // next mpc for this micro word wire [2:0] misc_control ; wire buf_dat_tran ; wire [1:0] buf_c1c0 ; // type of UNIBUs bus cycle: c1, C0 wire enab_maint ; wire load_ba ; wire long_cycle_l ; wire aux_control ; wire [4:0] _e82_addr ; // input to e82 address lines, unlabeld, function code s3..s0 wire [7:0] _e82_q ; // data output wire [3:0] alu_func ;// ALU s3..s0 wire alu_mode ; wire alu_cin_l ; wire [1:0] bleg ; // bleg control 01,00 wire [4:0] _e87_addr ; // input to e87 address lines, decode B,BX,OVX,DBE wire [7:0] _e87_q ; // data output wire [1:0] b_mode_l ; // BMODE 01,00 wire [1:0] bx_mode_l ; // BXMODE 01,00 wire [1:0] shift_mux_l ; // 01,00 wire enab_ovx_l ; wire enab_dbe_l ; wire [1:0] ssmux ; //ss01, ss00 wire [1:0] amux_l ; // amux s1, s0 wire [4:0] _e102_addr ; // encode control lines for microbranch wire [7:0] _e102_q ; // data output wire but_alu_out_mpc7 ; // if 1: add certain signals to mpc wire but_cc_n_mpc6 ; // wire but_bxreg01_mpc5 ; // wire but_bxreg00_mpc4 ; // wire but_sp15_mpc3 ; // wire but_count05_mpc2 ; // wire but_cc_z_mpc1 ; // wire but_ir09_mpc0 ; // wire [1:0] spa_src_sel ; // scratch pad source select wire [1:0] spa_dst_sel ; // scratch pad destination select wire force_rsv1_l ; wire previous_mode_l ; // last memory management mode wire but_service ; // wire force_kernel ; // wire [3:0] rom_spa ; // netx scratch pad register addr // wire the fields assign mpc_next[8] = ustore_primary_q[0] ; // next mpc is encoded bit reveresed assign mpc_next[7] = ustore_primary_q[1] ; assign mpc_next[6] = ustore_primary_q[2] ; assign mpc_next[5] = ustore_primary_q[3] ; assign mpc_next[4] = ustore_primary_q[4] ; assign mpc_next[3] = ustore_primary_q[5] ; assign mpc_next[2] = ustore_primary_q[6] ; assign mpc_next[1] = ustore_primary_q[7] ; assign mpc_next[0] = ustore_primary_q[8] ; assign misc_control[2] = ustore_primary_q[9] ; assign misc_control[1] = ustore_primary_q[10] ; assign misc_control[0] = ustore_primary_q[11] ; assign buf_dat_tran = ustore_primary_q[12] ; assign buf_c1c0[1] = ustore_primary_q[13] ; assign buf_c1c0[0] = ustore_primary_q[14] ; assign enab_maint = ustore_primary_q[15] ; // attention: error in DEC dock! assign load_ba = ustore_primary_q[17] ; assign long_cycle_l = ustore_primary_q[16] ; // assign load_ba = ustore_primary_q[16] ; // assign long_cycle = ustore_primary_q[17] ; assign aux_control = ustore_primary_q[18] ; // alu signal generation with e82 = n82s123 assign _e82_addr[1] = ustore_primary_q[19] ; // A1 = pin 11 assign _e82_addr[3] = ustore_primary_q[20] ; // A3 = pin 13 assign _e82_addr[2] = ustore_primary_q[21] ; // A2 = pin 12 assign _e82_addr[0] = ustore_primary_q[22] ; // A0 = pin 10 assign _e82_addr[4] = ustore_primary_q[23] ; // A4 = pin 14 // output of e82 controls the alu assign alu_func[3] = ~_e82_q[0] ; // O1 = pin 1, + inverter E81 assign alu_func[2] = ~_e82_q[1] ; // O2 = pin 2 assign alu_func[1] = ~_e82_q[3] ; // O4 = pin 4 assign alu_func[0] = ~_e82_q[4] ; // O5 = pin 5 assign alu_mode = _e82_q[2] ; // O3 = pin 3 assign alu_cin_l = _e82_q[5] ; // O6 = pin 6 assign bleg[1] = _e82_q[6] ; // O7 = pin 7 assign bleg[0] = _e82_q[7] ; // O8 = pin 9 // BX,B,OVX,DBE signal generation with E87 = N82S123 assign _e87_addr[0] = 0 ; // A0 = pin 10 assign _e87_addr[1] = ustore_primary_q[24] ; // A1 = pin 11 assign _e87_addr[4] = ustore_primary_q[25] ; // A4 = pin 14 assign _e87_addr[2] = ustore_primary_q[26] ; // A2 = pin 12 assign _e87_addr[3] = ustore_primary_q[27] ; // A3 = pin 13 assign b_mode_l[1] = ~_e87_q[0] ; // O1 = pin 1 + inverter E91 assign b_mode_l[0] = ~_e87_q[1] ; // O2 = pin 2 assign bx_mode_l[1] = _e87_q[2] ; // O3 = pin 3 assign bx_mode_l[0] = _e87_q[3] ; // O4 = pin 4 assign shift_mux_l[1] = _e87_q[4] ; // O5 = pin 5 assign shift_mux_l[0] = _e87_q[5] ; // O6 = pin 6 assign enab_ovx_l = _e87_q[6] ; // O7 = pin 7 assign enab_dbe_l = _e87_q[7] ; // O8 = pin 9 assign ssmux[1] = ustore_primary_q[28] ; assign ssmux[0] = ustore_primary_q[29] ; assign amux_l[1] = ustore_primary_q[30] ; assign amux_l[0] = ustore_primary_q[31] ; // encode control lines for microbranch with E102 = N82S123 assign _e102_addr[1] = ustore_primary_q[32] ; // A1 = pin 11 assign _e102_addr[4] = ustore_primary_q[33] ; // A4 = pin 14 assign _e102_addr[2] = ustore_primary_q[34] ; // A2 = pin 12 assign _e102_addr[3] = ustore_primary_q[35] ; // A3 = pin 13 assign _e102_addr[0] = 1 ; // A0 = pin 10 assign but_alu_out_mpc7 = _e102_q[0] ; // O1 = pin 1 assign but_cc_n_mpc6 = _e102_q[1] ; // O2 = pin 2 assign but_bxreg01_mpc5 = _e102_q[3] ; // O4 = pin 4 assign but_bxreg00_mpc4 = _e102_q[4] ; // O5 = pin 5 assign but_sp15_mpc3 = _e102_q[2] ; // O3 = pin 3 assign but_count05_mpc2 = _e102_q[5] ; // O6 = pin 6 assign but_cc_z_mpc1 = _e102_q[6] ; // O7 = pin 7 assign but_ir09_mpc0 = _e102_q[7] ; // O8 = pin 9 assign spa_src_sel[1] = ustore_primary_q[36] ; // scratch pad source select assign spa_src_sel[0] = ustore_primary_q[37] ; assign spa_dst_sel[1] = ustore_primary_q[38] ; // scratch pad destination select assign spa_dst_sel[0] = ustore_primary_q[39] ; assign force_rsv1_l = ustore_primary_q[40] ; assign previous_mode_l = ustore_primary_q[41] ; // last memory management mode assign but_service = ustore_primary_q[42] ; assign force_kernel = ustore_primary_q[43] ; assign rom_spa[3] = ustore_primary_q[44] ; // netx scratch pad register addr assign rom_spa[2] = ustore_primary_q[45] ; assign rom_spa[1] = ustore_primary_q[46] ; assign rom_spa[0] = ustore_primary_q[47] ; /***************** print all micro code words *****************/ integer fileid ; integer i, j, empty ; // save for every mpc the next address reg [8:0]mpc_next_table[0:511] ; initial begin fileid = $fopen("m8266_ucode.out", "w"); if (fileid == 0) begin $display("ERROR : CAN NOT OPEN THE FILE"); end // build jump table mpc = 0 ; for (i=0 ; i < 512 ; i = i+1) begin #1 // necessary for evaluation!!! mpc_next_table[i] = mpc_next ; mpc = mpc + 1 ; end mpc = 0 ; for (i=0 ; i < 512 ; i = i+1) begin #1 // necessary for evaluation!!! // $display("B %o: %b", mpc, ustore_primary_q) ; print_uword_fields ; mpc = mpc + 1 ; end $fclose(fileid) ; end reg [256*8:0] s; // string /*** function which prints one micro word with addr 'mpc' ***/ task print_uword_fields ; begin $fwrite(fileid, "***** PDP-11/34a micro code word for MPC = %o *****\n", mpc); $fwrite(fileid, " (MSB is left, indented fields generated by expansion ROMs)\n"); $fwrite(fileid, "micro word........ = %b %b %b %b %b %b %b %b %b %b %b %b\n", ustore_primary_q[47:44], ustore_primary_q[43:40], ustore_primary_q[39:36], ustore_primary_q[35:32], ustore_primary_q[31:28], ustore_primary_q[27:24], ustore_primary_q[23:20], ustore_primary_q[19:16], ustore_primary_q[15:12], ustore_primary_q[11:8], ustore_primary_q[7:4], ustore_primary_q[3:0] ); $fwrite(fileid, " from ROM: E105 E103 E104 E100 E98 E97 E99 E106 E107 E108 E109 E110\n"); // which steps can call this micro word $fwrite(fileid, "Called by......... = "); empty = 1 ; for (j=0 ; j < 512 ; j = j+1) begin if (mpc_next_table[j] == mpc) begin $fwrite(fileid, "%o ", j[8:0]) ; empty = 0 ; end end if (empty == 1) // no direct jumps to this uword found $fwrite(fileid, "IR or BUT only") ; $fwrite(fileid, "\n") ; $fwrite(fileid, "NEXT MPC.......... = %o\n", mpc_next) ; case (misc_control) 1: s = "LOAD IR L" ; 2: s = "LOAD PSW L" ; 3: s = "LOAD CC L" ; 4: s = "BUT DEST L" ; 5: s = "ENAB STOV L" ; 6: s = "LOAD COUNT L" ; 7: s = "CLK COUNT L" ; default: s = "?" ; endcase $fwrite(fileid, "Misc Control...... = %b = %0s\n", misc_control, s) ; $fwrite(fileid, "BUF DAT TRAN...... = %b\n", buf_dat_tran) ; case (buf_c1c0) 0: s = "DATI" ; 1: s = "DATIP" ; 2: s = "DATO" ; 3: s = "DATOB" ; endcase $fwrite(fileid, "Bus Control ...... = %b = %0s\n", buf_c1c0, s) ; $fwrite(fileid, "ENAB MAINT........ = %b\n", enab_maint) ; $fwrite(fileid, "LOAD BAR.......... = %b\n", load_ba) ; $fwrite(fileid, "LONG CYCLE L...... = %b\n", long_cycle_l) ; $fwrite(fileid, "AUX CONTROL....... = %b\n", aux_control) ; $fwrite(fileid, "_e82_addr......... = %b\n", _e82_addr) ; $fwrite(fileid, " _e82_data....... = %b\n", _e82_q) ; // see 74181 data sheet // symbol interpretion: https://en.wikipedia.org/wiki/List_of_logic_symbols // Table for "High operands". // comments: listed on Table 4-2 on page 4-7 case (alu_mode) 0: // mode=L: arithmetic. case ({~alu_cin_l,alu_func}) // Carry in = 0 5'b00000: s= "A" ; 5'b00001: s= "A | B" ; 5'b00010: s= "A | ~B" ; 5'b00011: s= "minus 1" ; 5'b00100: s= "A plus (A & ~B)" ; 5'b00101: s= "(A | B) plus (A & ~B)" ; 5'b00110: s= "A minus B minus 1" ; 5'b00111: s= "(A & B) minus 1" ; 5'b01000: s= "A plus (A & B)" ; 5'b01001: s= "A plus B" ; 5'b01010: s= "(A | ~B) plus (A & B)" ; 5'b01011: s= "(A & B) minus 1" ; 5'b01100: s= "A plus A (shift)" ; 5'b01101: s= "(A | B) plus A" ; 5'b01110: s= "(A | ~B) plus A" ; 5'b01111: s= "A minus 1" ; // carry in = 1: always "plus 1" 5'b10000: s= "A plus 1" ; 5'b10001: s= "(A | B) plus 1" ; 5'b10010: s= "(A | ~B) plus 1" ; 5'b10011: s= "0" ; 5'b10100: s= "A plus (A & ~B) plus 1" ; 5'b10101: s= "(A | B) plus (A & ~B) plus 1" ; 5'b10110: s= "A minus B" ; 5'b10111: s= "(A & B)" ; 5'b11000: s= "A plus (A & B) plus 1" ; 5'b11001: s= "A plus B plus 1" ; 5'b11010: s= "(A | ~B) plus (A & B) plus 1" ; 5'b11011: s= "(A & B)" ; 5'b11100: s= "A plus A plus 1" ; 5'b11101: s= "(A | B) plus A plus 1" ; 5'b11110: s= "(A | ~B) plus A plus 1" ; 5'b11111: s= "A" ; endcase 1: // mode=H: logic case (alu_func) 4'b0000: s= "~A" ; 4'b0001: s= "~A | ~B" ; 4'b0010: s= "~A & B" ; 4'b0011: s= "Logic 0" ; 4'b0100: s= "~(A & B)" ; 4'b0101: s= "~B" ; 4'b0110: s= "A xor B" ; 4'b0111: s= "A & ~B" ; 4'b1000: s= "~A | B" ; 4'b1001: s= "~A xor ~B" ; 4'b1010: s= "B" ; 4'b1011: s= "A & B" ; 4'b1100: s= "logic 1" ; 4'b1101: s= "A | ~B" ; 4'b1110: s= "A | B" ; 4'b1111: s= "A" ; endcase endcase /* original table 4-2 on page 4-7 .. .trash?? case ({alu_func,~alu_cin_l,alu_mode}) 6'b001101: s = "ZERO" ; 6'b000001: s = "A" ; 6'b000000: s = "A plus 1" ; 6'b111110: s = "A minus 1" ; 6'b011000: s = "A minus B" ; 6'b111101: s = "A" ; 6'b101001: s = "B" ; 6'b100110: s = "A plus B" ; 6'b101101: s = "A B" ; 6'b001001: s = "A B" ; 6'b100000: s = "A plus B plus 1" ; 6'b110010: s = "A plus A" ; 6'b010101: s = "B" ; 6'b110000: s = "A plus A plus 1" ; 6'b011001: s = "A + B" ; default: s = "?" ; endcase */ $fwrite(fileid, " ALU FUNC,MODE,CIN_L= %b,%b,%b = %0s\n", alu_func, alu_mode, alu_cin_l, s); case (bleg) // Figure 4-9 "BMUX Block Diagram", page 4-16 0: s = "B-REG to BMUX" ; 1: s = "BX-REG to BMUX" ; 2: s = "+16 to BMUX" ; 3: s = "+1 to BMUX" ; default: s = "?" ; endcase $fwrite(fileid, " BLEG............ = %b = %0s\n", bleg, s); $fwrite(fileid, "_e87_addr......... = %b\n", _e87_addr) ; $fwrite(fileid, " _e87_data....... = %b\n", _e87_q) ; case ({~b_mode_l[1],~b_mode_l[0]}) // Figure 4-6 "B Leg Block Diagram", page 4-12 0: s = "HOLD" ; 1: s = "SHIFT RIGHT" ; 2: s = "SHIFT LEFT" ; 3: s = "LOAD" ; default: s = "?" ; endcase $fwrite(fileid, " B MODE L........ = %b = %0s\n", b_mode_l, s) ; case ({~bx_mode_l[1],~bx_mode_l[0]}) // Figure 4-8 "BX REG Block Diagram", page 4-15 0: s = "HOLD" ; 1: s = "SHIFT RIGHT" ; 2: s = "SHIFT LEFT" ; 3: s = "LOAD" ; default: s = "?" ; endcase $fwrite(fileid, " BX MODE L....... = %b = %0s\n", bx_mode_l, s) ; $fwrite(fileid, " SHIFT MUX L..... = %b\n", shift_mux_l) ; $fwrite(fileid, " ENAB OVX L...... = %b\n", enab_ovx_l) ; $fwrite(fileid, " ENAB DBE L...... = %b\n", enab_dbe_l) ; case ({ssmux[1],ssmux[0]}) 0: s = "Straight" ; 1: s = "Sign Extend" ; 2: s = "Swap Bytes" ; 3: s = "External Data" ; default: s = "?" ; endcase $fwrite(fileid, "SSMUX SS.......... = %b = %0s\n", ssmux, s) ; case ({~amux_l[1],~amux_l[0]}) // Figure 4-11 " AMUX" page 4-22 0: s = "Unibus" ; 1: s = "Constants" ; 2: s = "ALU" ; 3: s = "PSW" ; default: s = "?" ; endcase $fwrite(fileid, "AMUX L............ = %b = %0s\n", amux_l, s) ; $fwrite(fileid, "_e102_addr........ = %b\n", _e102_addr) ; $fwrite(fileid, " _e102_data...... = %b\n", _e102_q) ; $fwrite(fileid, " but_alu_out_mpc7 = %b\n", but_alu_out_mpc7); $fwrite(fileid, " but_cc_n_mpc6... = %b\n", but_cc_n_mpc6); $fwrite(fileid, " but_bxreg01_mpc5 = %b\n", but_bxreg01_mpc5); $fwrite(fileid, " but_bxreg00_mpc4 = %b\n", but_bxreg00_mpc4); $fwrite(fileid, " but_sp15_mpc3... = %b\n", but_sp15_mpc3); $fwrite(fileid, " but_count05_mpc2 = %b\n", but_count05_mpc2); $fwrite(fileid, " but_cc_z_mpc1... = %b\n", but_cc_z_mpc1); $fwrite(fileid, " but_ir09_mpc0... = %b\n", but_ir09_mpc0); case (spa_src_sel) 0: s = "ROM" ; 1: s = "RS" ; 2: s = "RD" ; 3: s = "RBA" ; default: s = "?" ; endcase $fwrite(fileid, "SPA SRC SEL....... = %b = %0s\n", spa_src_sel, s) ; case (spa_dst_sel) 0: s = "ROM" ; 1: s = "RS" ; 2: s = "RD" ; 3: s = "RBA" ; default: s = "?" ; endcase $fwrite(fileid, "SPA DST SEL....... = %b = %0s\n", spa_dst_sel, s) ; $fwrite(fileid, "FORCE RSV1 L...... = %b\n", force_rsv1_l) ; $fwrite(fileid, "PREVIOUS MODE L... = %b\n", previous_mode_l) ; $fwrite(fileid, "BUT SERVICE....... = %b\n", but_service) ; $fwrite(fileid, "FORCE KERNEL..... = %b\n", force_kernel) ; $fwrite(fileid, "ROM SPA.......... = %b\n", rom_spa) ; $fwrite(fileid, "\n\n\n"); end endtask // Instantiate the primary 512x48 micro store m8266_ustore_primary ustore_primary( .mpc(mpc), .q(ustore_primary_q) ) ; // Instantiating secondary ROMS E82,E87,E102 m8266_e82 e82( .a(_e82_addr), .q(_e82_q) ) ; m8266_e87 e87( .a(_e87_addr), .q(_e87_q) ) ; m8266_e102 e102( .a(_e102_addr), .q(_e102_q) ) ; endmodule