-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The reverse engineering of M4 processor is completed, the synchronous model running on real FPGA is introduced. The synchronous M4 model: - runs on top of real FPGAs - supports Wishbone compatible front-end bus - ported and tested on multiple development boards Also bug with ena_ms frequency was fixed, the 1MHz ena_us was divided by 1024 instead of 1000 resulting in 976Hz ena_ms strobe frequency (was missed "else" keyword). The system timer frequency was not affected. Signed-off-by: 1801BM1 <[email protected]>
- Loading branch information
Showing
36 changed files
with
2,102 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// | ||
// Copyright (c) 2020 by [email protected] | ||
//______________________________________________________________________________ | ||
// | ||
// Four-bit Microprocessor Slice | ||
// | ||
module am4_alu | ||
( | ||
input clk, // clock positive | ||
input ena, // clock enable | ||
input [8:0] i, // operation code | ||
input [3:0] a, // port A address (readonly) | ||
input [3:0] b, // port B address (read/write) | ||
input [15:0] d, // direct data input | ||
output [15:0] y, // data output | ||
output [15:0] r, // ram[a] output | ||
// | ||
input cin, // carry input | ||
output c8, // carry output, LSB | ||
output c16, // carry output, MSB | ||
output v8, // arithmetic overflow, LSB | ||
output v16, // arithmetic overflow, MSB | ||
output zl, // zero flag, LSB | ||
output zh, // zero flag, MSB | ||
output f7, // msb of LSB | ||
output f15, // msb of MSB | ||
// | ||
input ram0_i, // shift register stack lsb LSB | ||
output ram0_o, // | ||
input ram7_i, // shift register stack msb LSB | ||
output ram7_o, // | ||
input ram8_i, // shift register stack lsb MSB | ||
output ram8_o, // | ||
input ram15_i, // shift register stack msb MSB | ||
output ram15_o, // | ||
input q0_i, // shift Q-register lsb LSB | ||
output q0_o, // | ||
input q15_i, // shift Q-register msb MSB | ||
output q15_o // | ||
); | ||
|
||
//______________________________________________________________________________ | ||
// | ||
reg [15:0] q_ram[15:0]; // RAM array | ||
wire [15:0] i_ram; // RAM input mux | ||
// | ||
reg [15:0] q_reg; // Q register | ||
wire [15:0] q_mux; // Q register input mux | ||
// | ||
wire [15:0] r_alu; // ALU input mux R | ||
wire [15:0] r_ext; // | ||
wire [15:0] s_alu; // ALU input mux S | ||
wire [15:0] s_ext; // | ||
wire [15:0] f_alu; // ALU result output | ||
// | ||
wire c6, c7, c14, c15; // carries | ||
wire [16:0] sum; // sum to get carries | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// Initialization to eliminate uncertain simulation | ||
// | ||
integer m; | ||
|
||
initial | ||
begin | ||
for (m=0; m<16; m = m + 1) | ||
q_ram[m] = 4'b0000; | ||
q_reg = 4'b0000; | ||
end | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// RAM registers and RAM input mux | ||
// | ||
assign i_ram = (i[8:7] == 2'b00) ? 16'h0000 : // QREG, NOP | ||
(i[8:7] == 2'b01) ? f_alu : // RAMA, RAMF - load | ||
(i[8:7] == 2'b10) ? {ram15_i, f_alu[15:9], // | ||
ram7_i, f_alu[7:1]} : // RAMQD, RAMD - shift down/right | ||
(i[8:7] == 2'b11) ? {f_alu[14:8], ram8_i, // | ||
f_alu[6:0], ram0_i} : // RAMQU, RAMU - shift up/left | ||
16'h0000; // default | ||
|
||
always @(posedge clk) if ((i[8:7] != 2'b00) & ena) q_ram[b] <= i_ram; | ||
|
||
assign ram0_o = f_alu[0]; | ||
assign ram7_o = f_alu[7]; | ||
assign ram8_o = f_alu[8]; | ||
assign ram15_o = f_alu[15]; | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// Q-register input mux and latches | ||
// | ||
assign q_mux = (i[8:6] == 3'b000) ? f_alu : // QREG | ||
(i[8:6] == 3'b100) ? {q15_i, q_reg[15:1]} : // RAMQD - shift down/right | ||
(i[8:6] == 3'b110) ? {q_reg[14:0], q0_i} : q_reg; // RAMQU - shift up/left | ||
|
||
assign q0_o = q_reg[0]; | ||
assign q15_o = q_reg[15]; | ||
|
||
always @(posedge clk) if (ena) q_reg <= q_mux; | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// Y-output mux and RAMA output | ||
// | ||
assign y = (i[8:6] == 3'b010) ? q_ram[a] : f_alu; | ||
assign r = q_ram[a]; | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// ALU input muxes | ||
// | ||
assign r_alu = (i[2:0] == 3'b000) ? q_ram[a] : // AQ | ||
(i[2:0] == 3'b001) ? q_ram[a] : // AB | ||
(i[2:0] == 3'b010) ? 16'h0000 : // ZQ | ||
(i[2:0] == 3'b011) ? 16'h0000 : // ZB | ||
(i[2:0] == 3'b100) ? 16'h0000 : d; // ZA, DA, DQ, DZ | ||
|
||
assign s_alu = (i[2:0] == 3'b000) ? q_reg : // AQ | ||
(i[2:0] == 3'b001) ? q_ram[b] : // AB | ||
(i[2:0] == 3'b010) ? q_reg : // ZQ | ||
(i[2:0] == 3'b011) ? q_ram[b] : // ZB | ||
(i[2:0] == 3'b100) ? q_ram[a] : // ZA | ||
(i[2:0] == 3'b101) ? q_ram[a] : // DA | ||
(i[2:0] == 3'b110) ? q_reg : 16'h0000; // DQ, DZ | ||
|
||
assign r_ext = ( (i[5:3] == 3'b001) | ||
| (i[5:3] == 3'b101) | ||
| (i[5:3] == 3'b110)) ? ~r_alu : r_alu; | ||
|
||
assign s_ext = (i[5:3] == 3'b010) ? ~s_alu : s_alu; | ||
assign sum = {1'b0, r_ext} + {1'b0, s_ext} + {16'h0000, cin}; | ||
|
||
// | ||
// Carry from alu_f[n]->alu_f[n+1] | ||
// | ||
assign c6 = s_ext[7] ^ r_ext[7] ^ sum[7]; // f_alu[6]->f_alu[7] | ||
assign c7 = s_ext[8] ^ r_ext[8] ^ sum[8]; // f_alu[7]->f_alu[8] | ||
assign c14 = s_ext[15] ^ r_ext[15] ^ sum[15]; // f_alu[14]->f_alu[15] | ||
assign c15 = sum[16]; | ||
// | ||
// ALU result | ||
// | ||
assign f_alu = (i[5:3] == 3'b000) ? sum[15:0] : // ADD | ||
(i[5:3] == 3'b001) ? sum[15:0] : // SUBR | ||
(i[5:3] == 3'b010) ? sum[15:0] : // SUBS | ||
(i[5:3] == 3'b011) ? r_ext | s_ext : // OR | ||
(i[5:3] == 3'b100) ? r_ext & s_ext : // AND | ||
(i[5:3] == 3'b101) ? r_ext & s_ext : // NOTRS | ||
(i[5:3] == 3'b110) ? ~r_ext ^ s_ext : // EXOR | ||
(i[5:3] == 3'b111) ? ~r_ext ^ s_ext : 16'h0000; // EXNOR | ||
|
||
// | ||
// The carry and overflow flags over logical instructions | ||
// are not used by microcode, we can simplify | ||
// | ||
assign c8 = (i[5:3] == 3'b000) ? c7 : // ADD | ||
(i[5:3] == 3'b001) ? c7 : // SUBR | ||
(i[5:3] == 3'b010) ? c7 : cin; // SUBS | ||
|
||
assign c16 = (i[5:3] == 3'b000) ? c15 : // ADD | ||
(i[5:3] == 3'b001) ? c15 : // SUBR | ||
(i[5:3] == 3'b010) ? c15 : cin; // SUBS | ||
|
||
assign v8 = (i[5:3] == 3'b000) ? c6 ^ c7 : // ADD | ||
(i[5:3] == 3'b001) ? c6 ^ c7 : // SUBR | ||
(i[5:3] == 3'b010) ? c6 ^ c7 : 1'b0; // SUBS | ||
|
||
assign v16 = (i[5:3] == 3'b000) ? c14 ^ c15 : // ADD | ||
(i[5:3] == 3'b001) ? c14 ^ c15 : // SUBR | ||
(i[5:3] == 3'b010) ? c14 ^ c15 : 1'b0; // SUBS | ||
|
||
assign f7 = f_alu[7]; | ||
assign f15 = f_alu[15]; | ||
assign zl = ~|f_alu[7:0]; | ||
assign zh = ~|f_alu[15:8]; | ||
//______________________________________________________________________________ | ||
// | ||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// | ||
// Copyright (c) 2020 by [email protected] | ||
// | ||
//______________________________________________________________________________ | ||
// | ||
// M4 microcode ROM, for debug and simulating only | ||
// | ||
module mcrom | ||
( | ||
input clk, // input clock | ||
input ena, // clock enable | ||
input [9:0] addr, // instruction address | ||
output [55:0] data // output read opcode | ||
); | ||
|
||
//______________________________________________________________________________ | ||
// | ||
// Memory array and its inititialization with K1656RE1-001/007 content | ||
// | ||
reg [55:0] rom [0:1023]; | ||
reg [55:0] q; | ||
integer i; | ||
|
||
initial | ||
begin | ||
end | ||
|
||
|
||
initial | ||
begin | ||
for (i=0; i<1023; i = i + 1) | ||
begin | ||
rom[i] = 56'h00000000000000; | ||
end | ||
// | ||
// The filename for MicROM content might be explicitly | ||
// specified in synthesys/simulating tool settings | ||
// | ||
`ifdef M4_FILE_MICROM | ||
$readmemh(`M4_FILE_MICROM, rom); | ||
`else | ||
$readmemh("..\\..\\..\\..\\rom\\mc.rom", rom); | ||
`endif | ||
end | ||
|
||
//______________________________________________________________________________ | ||
// | ||
assign data = q; | ||
always @ (posedge clk) if (ena) q <= rom[addr]; | ||
|
||
endmodule | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// | ||
// Copyright (c) 2020 by [email protected] | ||
//______________________________________________________________________________ | ||
// | ||
// M4 processor PDP-11 instruction decoding PLM (D123, D136) | ||
// | ||
module plm_dec | ||
( | ||
input [15:0] ins, // PDP-11 instruction opcode | ||
output reg bf, // byte operation flag | ||
output reg [6:0] ad // address of microcode | ||
); | ||
|
||
wire rs = ins[11:9] == 3'b000; | ||
wire rd = ins[5:3] == 3'b000; | ||
|
||
always @(*) | ||
casex(ins) // clrb/comb/incb/decb | ||
16'o105xxx: bf = 1'b1; // negb/adcb/sbcb/tstb | ||
16'o1060xx: bf = 1'b1; // rorb | ||
16'o1061xx: bf = 1'b1; // rolb | ||
16'o1062xx: bf = 1'b1; // asrb | ||
16'o1063xx: bf = 1'b1; // aslb | ||
16'o1064xx: bf = 1'b1; // mtps | ||
16'o1067xx: bf = 1'b1; // mfps | ||
16'o11xxxx: bf = 1'b1; // movb | ||
16'o12xxxx: bf = 1'b1; // cmpb | ||
16'o13xxxx: bf = 1'b1; // bitb | ||
16'o14xxxx: bf = 1'b1; // bicb | ||
16'o15xxxx: bf = 1'b1; // bisb | ||
default: bf = 1'b0; | ||
endcase | ||
|
||
always @(*) | ||
casex(ins) | ||
16'o000000: ad = 7'h00; // halt | ||
16'o000001: ad = 7'h03; // wait | ||
16'o000002: ad = 7'h02; // rti | ||
16'o000003: ad = 7'h04; // bpt | ||
16'o000004: ad = 7'h07; // iot | ||
16'o000005: ad = 7'h06; // reset | ||
16'o000006: ad = 7'h02; // rtt | ||
16'o0001xx: ad = 7'h0E; // jmp | ||
16'o00020x: ad = 7'h36; // rts | ||
16'o00024x: ad = 7'h40; // clx | ||
16'o00025x: ad = 7'h40; // clx | ||
16'o00026x: ad = 7'h43; // sex | ||
16'o00027x: ad = 7'h43; // sex | ||
16'o0003xx: ad = ~rd ? 7'h41 // swab | ||
/* 16'o00030x: */ : 7'h44; // swab Rd | ||
16'o0004xx: ad = 7'h1F; // br | ||
16'o0005xx: ad = 7'h1F; // | ||
16'o0006xx: ad = 7'h1F; // | ||
16'o0007xx: ad = 7'h1F; // | ||
16'o001xxx: ad = 7'h1F; // bne/beq | ||
16'o002xxx: ad = 7'h1F; // bge/blt | ||
16'o003xxx: ad = 7'h1F; // bgt/ble | ||
16'o004xxx: ad = 7'h37; // jsr | ||
// | ||
16'o0050xx: ad = ~rd ? 7'h12 // clr | ||
/* 16'o00500x: */ : 7'h22; // clr Rd | ||
16'o0051xx: ad = ~rd ? 7'h14 // com | ||
/* 16'o00510x: */ : 7'h24; // com Rd | ||
16'o0052xx: ad = ~rd ? 7'h16 // inc | ||
/* 16'o00520x: */ : 7'h26; // inc Rd | ||
16'o0053xx: ad = ~rd ? 7'h18 // dec | ||
/* 16'o00530x: */ : 7'h28; // dec Rd | ||
16'o0054xx: ad = ~rd ? 7'h1A // neg | ||
/* 16'o00540x: */ : 7'h2A; // neg Rd | ||
16'o0055xx: ad = ~rd ? 7'h0D // adc | ||
/* 16'o00550x: */ : 7'h4D; // adc Rd | ||
16'o0056xx: ad = ~rd ? 7'h53 // sbc | ||
/* 16'o00560x: */ : 7'h4A; // sbc Rd | ||
16'o0057xx: ad = ~rd ? 7'h2C // tst | ||
/* 16'o00570x: */ : 7'h6C; // tst Rd | ||
16'o0060xx: ad = ~rd ? 7'h15 // ror | ||
/* 16'o00600x: */ : 7'h55; // ror Rd | ||
16'o0061xx: ad = ~rd ? 7'h17 // rol | ||
/* 16'o00610x: */ : 7'h56; // rol Rd | ||
16'o0062xx: ad = ~rd ? 7'h1B // asr | ||
/* 16'o00620x: */ : 7'h5B; // asr Rd | ||
16'o0063xx: ad = ~rd ? 7'h1D // asl | ||
/* 16'o00630x: */ : 7'h5C; // asl Rd | ||
16'o0064xx: ad = 7'h09; // mark | ||
16'o0067xx: ad = 7'h08; // sxt | ||
// | ||
16'o01xxxx: ad = (~rs | ~rd) ? 7'h31 // mov | ||
/* 16'o010x0x: */ : 7'h30; // mov Rs, Rd | ||
16'o02xxxx: ad = (~rs | ~rd) ? 7'h13 // cmp | ||
/* 16'o020x0x: */ : 7'h3A; // cmp Rs, Rd | ||
16'o03xxxx: ad = (~rs | ~rd) ? 7'h1C // bit | ||
/* 16'o030x0x: */ : 7'h3C; // bit Rs, Rd | ||
16'o04xxxx: ad = (~rs | ~rd) ? 7'h1E // bic | ||
/* 16'o040x0x: */ : 7'h3E; // bic Rs, Rd | ||
16'o05xxxx: ad = (~rs | ~rd) ? 7'h10 // bis | ||
/* 16'o050x0x: */ : 7'h20; // bis Rs, Rd | ||
16'o06xxxx: ad = ~rs ? 7'h35 // add | ||
/* 16'o060xxx: */ : ~rd ? 7'h34 // add Rs, xx | ||
/* 16'o060x0x: */ : 7'h74; // add Rs, Rd | ||
16'o070xxx: ad = 7'h47; // mul | ||
16'o071xxx: ad = 7'h48; // div | ||
16'o072xxx: ad = 7'h42; // ash | ||
16'o073xxx: ad = 7'h45; // ashc | ||
16'o074xxx: ad = 7'h0B; // xor | ||
16'o07500x: ad = 7'h0F; // fadd | ||
16'o07501x: ad = 7'h0F; // fsub | ||
16'o07502x: ad = 7'h0F; // fmul | ||
16'o07503x: ad = 7'h0F; // fdiv | ||
16'o077xxx: ad = 7'h0A; // sob | ||
// | ||
16'o100xxx: ad = 7'h1F; // bpl/bmi | ||
16'o101xxx: ad = 7'h1F; // bhi/blos | ||
16'o102xxx: ad = 7'h1F; // bvc/bvs | ||
16'o103xxx: ad = 7'h1F; // bcc/bcs | ||
16'o1040xx: ad = 7'h39; // emt | ||
16'o1041xx: ad = 7'h39; // emt | ||
16'o1042xx: ad = 7'h39; // emt | ||
16'o1043xx: ad = 7'h39; // emt | ||
16'o1044xx: ad = 7'h38; // trap | ||
16'o1045xx: ad = 7'h38; // trap | ||
16'o1046xx: ad = 7'h38; // trap | ||
16'o1047xx: ad = 7'h38; // trap | ||
16'o1050xx: ad = 7'h25; // clrb | ||
16'o1051xx: ad = 7'h27; // comb | ||
16'o1052xx: ad = 7'h29; // incb | ||
16'o1053xx: ad = 7'h2B; // decb | ||
16'o1054xx: ad = 7'h2D; // negb | ||
16'o1055xx: ad = 7'h51; // adcb | ||
16'o1056xx: ad = 7'h52; // sbcb | ||
16'o1057xx: ad = 7'h2F; // tstb | ||
16'o1060xx: ad = 7'h54; // rorb | ||
16'o1061xx: ad = 7'h59; // rolb | ||
16'o1062xx: ad = 7'h5A; // asrb | ||
16'o1063xx: ad = 7'h5F; // aslb | ||
16'o1064xx: ad = 7'h2E; // mtps | ||
16'o1067xx: ad = 7'h0C; // mfps | ||
16'o11xxxx: ad = (~rs | ~rd) ? 7'h33 // movb | ||
/* 16'o110x0x: */ : 7'h32; // movb Rd, Rs | ||
16'o12xxxx: ad = 7'h3D; // cmpb | ||
16'o13xxxx: ad = 7'h3F; // bitb | ||
16'o14xxxx: ad = 7'h21; // bicb | ||
16'o15xxxx: ad = 7'h23; // bisb | ||
16'o16xxxx: ad = (~rs | ~rd) ? 7'h19 // sub | ||
/* 16'o160x0x: */ : 7'h3B; // sub Rd, Rs | ||
default: ad = 7'h01; // undefined | ||
endcase | ||
|
||
endmodule |
Oops, something went wrong.