module cons( input wire clk, input wire reset ); // TODO wire int = 0; wire vmaint = 0; /* * Timing and PDP-11 Interface */ reg opcclk; reg nop11; reg idebug; reg ureset; reg sstep; reg run; reg errstop; reg speed = 0; // error bits reg higherr; reg ipe; reg mpe; reg ape; reg pdlpe; reg mempe; reg dpe; reg spe; wire errhalt = mempe | pdlpe | ape | mpe | ipe | higherr | dpe | spe; wire errhaltN = errhalt & errstop; wire rgo = srun & ~errhaltN; wire ssgo = sstep & ~ssdone; wire igo = rgo | ssgo; reg srun; reg ssdone; always @(posedge clk) begin if(RESET) begin higherr <= 0; ipe <= 0; mpe <= 0; ape <= 0; pdlpe <= 0; mempe <= 0; dpe <= 0; spe <= 0; srun <= 0; end else begin if(clkedge) begin srun <= run; ssdone <= sstep; // hack, not in schematics: if(funct1) run <= 0; end if(run) srun <= 1; if(~sstep) ssdone <= 0; end end wire cyclestarted, cyclecompleted; assign cyclestarted = ~(cyclecompleted & ~tpr40); assign cyclecompleted = ~(cyclestarted & ~tpdone & igo); wire begincycle = ~mwait & igo & cyclecompleted; wire tpr0 = begincycle; wire #20 tpr20 = tpr0; wire #20 tpr40 = tpr20; wire #20 tpr60 = tpr40; wire #20 tpr80 = tpr60; wire #20 tpr100 = tpr80; wire #20 tpr120 = tpr100; wire #20 tpr140 = tpr120; wire #20 tpr160 = tpr140; wire #20 tpr180 = tpr160; wire #20 tpr200 = tpr180; wire #25 tpslow = tpr100; wire #25 tpfast = tpr60; wire tpclkr = speed ? tpr200 : ilong ? tpslow : tpfast; wire #20 tp20 = tpclkr; wire #20 tp40 = tp20; wire #20 tp60 = tp40; wire #20 tp80 = tp60; wire #20 tp100 = tp80; wire #20 tp120 = tp100; wire #20 tp140 = tp120; wire #20 tp160 = tp140; wire #20 tp180 = tp160; wire #20 tp200 = tp180; wire #10 tpwps = tp40; wire #15 tpwpr = tp80; wire #25 tpdone = tp80; wire tpclk, tpclk_n; assign tpclk = ~(~tpr0 & tpclk_n); assign tpclk_n = ~(~tpclkr & ~RESET & tpclk); wire tpwp, tpwp_n; assign tpwp = ~(~tpwps & tpwp_n); assign tpwp_n = ~(~tpwpr & ~RESET & tpwp); wire CLK = tpclk; wire RESET = ureset; wire wp = tpwp; // cheap synchronization reg CLK0, CLK1; wire clkedge = CLK0 & ~CLK1; always @(posedge clk) begin CLK0 <= CLK; CLK1 <= CLK0; end /* * DEBUG */ reg [43:0] debug; wire [15:0] dat = 0; wire datld0 = 0; wire datld1 = 0; wire datld2 = 0; always @(posedge clk) begin if(datld0) debug[15:0] <= dat; if(datld1) debug[31:16] <= dat; if(datld2) debug[44:32] <= dat; end /* * PC */ wire jump = irjump & cond; wire jtj = jump & (ir[9:8] == 0); wire jtp = jump & (ir[9:8] == 1); wire jtr = jump & (ir[9:8] == 2); wire iwrite = jump & (ir[9:8] == 3); wire dispenb = irdisp & ~funct2; wire dtj = dispenb & ({dr,dp} == 0); wire dtp = dispenb & ({dr,dp} == 1); wire dtr = dispenb & ({dr,dp} == 2); wire dfall = dispenb & ({dr,dp} == 3); wire nop = inop | nop11; wire ipopj = ir[38] & ~nop; wire popj = ipopj | iwrited; wire dispn = dispenb & dn; wire jumpn = irjump & cond & ir[7]; wire n = dispn | jumpn | iwrited; wire spush = jtp | dtp | iwrite | destspc; wire spop = jtr | dtr | popj | srcspc&ir[27]; wire spcnt = spush | spop; wire swp = wp & spushd; reg pdlwrited; reg pwidx; reg spushd; reg iwrited; always @(posedge clk) begin if(RESET) begin pdlwrited <= 0; pwidx <= 0; spushd <= 0; iwrited <= 0; end else if(clkedge) begin pdlwrited <= pdlwrite; pwidx <= destpdl_x; spushd <= spush; iwrited <= iwrite; end end wire [1:0] pcs; assign pcs[0] = jtj | jtp | iwrite | dtj | dtp; assign pcs[1] = jump | dtr | popj; reg [11:0] pc; wire [11:0] ipc = pc + 1; reg [11:0] npc; always @(*) case(pcs) 2'b00: npc <= ipc; 2'b01: npc <= dpc; 2'b10: npc <= spc[11:0]; 2'b11: npc <= ir[23:12]; endcase always @(posedge clk) begin if(clkedge) pc <= npc; end /* * OLD PC */ reg [11:0] opc0; reg [11:0] opc1; reg [11:0] opc2; reg [11:0] opc3; reg [11:0] opc4; reg [11:0] opc5; reg [11:0] opc6; reg [11:0] opc7; always @(posedge clk) begin if(clkedge) begin opc0 <= pc; opc1 <= opc0; opc2 <= opc1; opc3 <= opc2; opc4 <= opc3; opc5 <= opc4; opc6 <= opc5; opc7 <= opc6; end end /* * I */ wire ienb = ~idebug; wire iwc = wp & iwrited; reg [44:0] iwl; reg [44:0] imem[0:'o10000-1]; reg [43:0] idbg; wire [44:0] i = {45{ienb}}&imem[pc] | idbg; reg [44:0] ir; reg imodd; reg inop; always @(posedge clk) begin if(RESET) begin ir <= 0; end else if(clkedge) begin ir <= i; imodd <= imod; inop <= n; iwl[31:0] <= m; iwl[43:32] <= a[11:0]; end if(iwc) imem[pc] <= iwl; end always @(*) begin iwl[44] <= ^iwl[43:0]; // i hope this is right case({idebug,destimod0}) 2'b00: idbg[23:0] <= 0; 2'b01: idbg[23:0] <= debug[23:0]; 2'b10: idbg[23:0] <= ob[23:0]; 2'b11: idbg[23:0] <= debug[23:0]; endcase case({idebug,destimod1}) 2'b00: idbg[43:24] <= 0; 2'b01: idbg[43:24] <= debug[19:0]; 2'b10: idbg[43:24] <= ob[19:0]; 2'b11: idbg[43:24] <= debug[19:0]; endcase end wire ilong = ir[41]; wire iralu = ~nop & (ir[40:39] == 0); wire irdisp = ~nop & (ir[40:39] == 1); wire irjump = ~nop & (ir[40:39] == 2); wire irbyte = ~nop & (ir[40:39] == 3); wire funct0 = ~nop & (ir[11:10] == 0); wire funct1 = ~nop & (ir[11:10] == 1); wire funct2 = ~nop & (ir[11:10] == 2); wire funct3 = ~nop & (ir[11:10] == 3); wire subs0 = ir[28:27] == 0; wire subs1 = ir[28:27] == 1; wire subs2 = ir[28:27] == 2; wire subs3 = ir[28:27] == 3; wire dest = iralu | irbyte; wire destm = dest & ~ir[23]; wire specalu = iralu & ir[9]; wire mul = specalu & (ir[5:4] == 0); wire div = specalu & (ir[5:4] == 1); wire destmemd = destm & (ir[22:19] == 'o01); wire destmemdw = destm & (ir[22:19] == 'o02); wire destmemdmap = destm & (ir[22:19] == 'o03); wire destvma = destm & (ir[22:19] == 'o04); wire destvmard = destm & (ir[22:19] == 'o05); wire destvmawr = destm & (ir[22:19] == 'o06); wire destvmamap = destm & (ir[22:19] == 'o07); wire destpdltop = destm & (ir[22:19] == 'o10); wire destpdl_p = destm & (ir[22:19] == 'o11); wire destpdl_x = destm & (ir[22:19] == 'o12); wire destpdlx = destm & (ir[22:19] == 'o13); wire destpdlp = destm & (ir[22:19] == 'o14); wire destspc = destm & (ir[22:19] == 'o15); wire destimod0 = destm & (ir[22:19] == 'o16); wire destimod1 = destm & (ir[22:19] == 'o17); wire destimod = destimod0 | destimod1; wire imod = idebug | destimod; wire srcmmpx = ir[29] & ~nop & (ir[26:24] == 2); wire srcspc = ir[29] & ~nop & (ir[26:24] == 5); wire srcpdl = ir[29] & ~nop & (ir[26:24] == 7); /* * DISP */ reg [15:0] dmem[0:'o2000-1]; wire dispwr = irdisp & funct2; wire dramw = wp & dispwr; wire [9:0] dadr = ir[23:14] | dmsk&r[6:0]; wire [15:0] d = dmem[dadr]; wire dr = d[14]; wire dp = d[13]; wire dn = d[12]; wire [11:0] dpc = d[11:0]; reg [7:0] dc; always @(posedge clk) begin if(clkedge) if(irdisp) dc <= ir[37:30]; if(dramw) dmem[dadr] <= ml[15:0]; end reg [6:0] dmsk; always @(*) begin case(ir[7:5]) 3'o0: dmsk <= 7'b0000000; 3'o1: dmsk <= 7'b0000001; 3'o2: dmsk <= 7'b0000011; 3'o3: dmsk <= 7'b0000111; 3'o4: dmsk <= 7'b0001111; 3'o5: dmsk <= 7'b0011111; 3'o6: dmsk <= 7'b0111111; 3'o7: dmsk <= 7'b1111111; endcase end /* * SPC */ reg [15:0] spcmem[0:'o40-1]; reg [15:0] spcl; reg [4:0] spcptr; wire [14:0] spc; wire [11:0] spca = spcl[11:0]; assign spc[14:12] = spcl[14:12]; assign spc[11:0] = spushd ? spcw[11:0] : spca[11:0]; wire spcpar = spcl[15]; wire [14:0] spcwa = destspc ? ob[14:0] : ipc[11:0]; reg [14:0] spcw; wire spcwpar = 0; always @(posedge clk) begin if(RESET) begin spcptr <= 0; // TODO not in hardware end else if(clkedge) begin if(spcnt) begin if(spush) spcptr <= spcptr + 1; else spcptr <= spcptr - 1; end spcw[11:0] <= n ? pc[11:0] : spcwa[11:0]; spcw[14:12] <= dispenb ? ir[36:34] : spcwa[14:12]; end if(swp) spcmem[spcptr] <= {spcwpar, spcw}; end // TODO: get rid of latch always @(*) if(CLK) spcl <= spcmem[spcptr]; /* * PDL */ reg [32:0] pdlmem[0:'o2000-1]; wire pwp = wp & pdlwrited; wire srcpdl_p = srcpdl & subs1; wire pdlcnt = srcpdl_p | destpdl_p; wire pdlwrite = destpdl_x | destpdl_p | destpdltop; wire pdlp = CLK ? ir[27] : ~pwidx; wire [9:0] pdla = pdlp ? pdlptr : pdlidx; reg [32:0] pdlbuf; reg [9:0] pdlptr; reg [9:0] pdlidx; always @(posedge clk) begin if(clkedge) begin if(pdlcnt) begin if(~srcpdl_p) pdlptr <= pdlptr + 1; else pdlptr <= pdlptr - 1; end if(destpdlp) pdlptr <= ob[9:0]; if(destpdlx) pdlidx <= ob[9:0]; end if(pwp) pdlmem[pdla] <= {lparity, l}; end // TODO: get rid of latch always @(*) if(CLK) pdlbuf <= pdlmem[pdla]; /* * L */ reg [31:0] l; wire lparity = 0; // TODO always @(posedge clk) if(clkedge) l <= ob; /* * A-MEM */ wire awe = wp & destad; reg destad; reg [7:0] awadr; wire [7:0] aadr = CLK ? ir[37:30] : awadr; reg [31:0] amem[0:'o400-1]; wire [31:0] am = amem[aadr]; reg [31:0] aml; wire apass = destad & (awadr == ir[37:30]); wire [31:0] a = apass ? l : aml; always @(posedge clk) begin if(RESET) begin destad <= 0; awadr[4:0] <= 0; end else if(clkedge) begin destad <= dest; awadr[4:0] <= ir[18:14]; awadr[7:5] <= destm ? 0 : ir[21:19]; end if(awe) amem[aadr] <= l; end // TODO: get rid of latch always @(*) if(CLK) aml <= am; /* * M-MEM */ wire mwp = wp & destmd; reg destmd; reg [4:0] mwadr; wire [4:0] madr = CLK ? ir[28:24] : mwadr; reg [31:0] mmem[0:'o40-1]; reg [31:0] ml; wire mpass = destmd & (mwadr == ir[28:24]); wire [2:0] msel = ir[29] ? ir[26:24] : mpass; always @(posedge clk) begin if(RESET) begin destmd <= 0; mwadr <= 0; end else if(clkedge) begin destmd <= destm; mwadr <= ir[18:14]; end if(mwp) mmem[madr] <= l; end // TODO: get rid of latch always @(*) // this seems wrong: // if(~CLK) ml <= mmem[madr]; if(CLK) ml <= mmem[madr]; reg [31:0] m; always @(*) case(msel) 3'o0: m <= ml; 3'o1: m <= l; 3'o2: m <= mmpx; 3'o3: m <= q; 3'o4: m <= {alucarry, alusgn, aluless, alueq, 8'b0, pdlptr, pdlidx}; 3'o5: m <= {spcptr, 12'b0, spc}; 3'o6: m <= dc; 3'o7: m <= pdlbuf[31:0]; endcase /* * SHIFT */ reg [31:0] sa; reg [31:0] r; always @(*) begin case(s[1:0]) 2'b00: sa <= m; 2'b01: sa <= {m[30:0], m[31]}; 2'b10: sa <= {m[29:0], m[31:30]}; 2'b11: sa <= {m[28:0], m[31:29]}; endcase case(s[4:2]) 3'b000: r <= sa; 3'b001: r <= {sa[27:0], sa[31:28]}; 3'b010: r <= {sa[23:0], sa[31:24]}; 3'b011: r <= {sa[19:0], sa[31:20]}; 3'b100: r <= {sa[15:0], sa[31:16]}; 3'b101: r <= {sa[11:0], sa[31:12]}; 3'b110: r <= {sa[7:0], sa[31:8]}; 3'b111: r <= {sa[3:0], sa[31:4]}; endcase end /* * MASK */ wire pcshthi = funct3 & pclb; wire shifthi = ir[4] ^ pcshthi; wire maskr = ~irbyte | ir[13]; wire [4:0] mskr = maskr ? {shifthi, ir[3:0]} : 0; wire mr = ~irbyte | ir[12]; wire [4:0] s = mr ? {shifthi, ir[3:0]} : 0; wire [4:0] mskl = mskr + ir[9:5]; reg [31:0] mask_l; reg [31:0] mask_r; wire [31:0] msk = mask_l & mask_r; wire [31:0] mo = msk & r | ~msk & a; always @(*) case(mskl) 5'o00: mask_l <= 32'b00000000000000000000000000000001; 5'o01: mask_l <= 32'b00000000000000000000000000000011; 5'o02: mask_l <= 32'b00000000000000000000000000000111; 5'o03: mask_l <= 32'b00000000000000000000000000001111; 5'o04: mask_l <= 32'b00000000000000000000000000011111; 5'o05: mask_l <= 32'b00000000000000000000000000111111; 5'o06: mask_l <= 32'b00000000000000000000000001111111; 5'o07: mask_l <= 32'b00000000000000000000000011111111; 5'o10: mask_l <= 32'b00000000000000000000000111111111; 5'o11: mask_l <= 32'b00000000000000000000001111111111; 5'o12: mask_l <= 32'b00000000000000000000011111111111; 5'o13: mask_l <= 32'b00000000000000000000111111111111; 5'o14: mask_l <= 32'b00000000000000000001111111111111; 5'o15: mask_l <= 32'b00000000000000000011111111111111; 5'o16: mask_l <= 32'b00000000000000000111111111111111; 5'o17: mask_l <= 32'b00000000000000001111111111111111; 5'o20: mask_l <= 32'b00000000000000011111111111111111; 5'o21: mask_l <= 32'b00000000000000111111111111111111; 5'o22: mask_l <= 32'b00000000000001111111111111111111; 5'o23: mask_l <= 32'b00000000000011111111111111111111; 5'o24: mask_l <= 32'b00000000000111111111111111111111; 5'o25: mask_l <= 32'b00000000001111111111111111111111; 5'o26: mask_l <= 32'b00000000011111111111111111111111; 5'o27: mask_l <= 32'b00000000111111111111111111111111; 5'o30: mask_l <= 32'b00000001111111111111111111111111; 5'o31: mask_l <= 32'b00000011111111111111111111111111; 5'o32: mask_l <= 32'b00000111111111111111111111111111; 5'o33: mask_l <= 32'b00001111111111111111111111111111; 5'o34: mask_l <= 32'b00011111111111111111111111111111; 5'o35: mask_l <= 32'b00111111111111111111111111111111; 5'o36: mask_l <= 32'b01111111111111111111111111111111; 5'o37: mask_l <= 32'b11111111111111111111111111111111; endcase always @(*) case(mskr) 5'o00: mask_r <= 32'b11111111111111111111111111111111; 5'o01: mask_r <= 32'b11111111111111111111111111111110; 5'o02: mask_r <= 32'b11111111111111111111111111111100; 5'o03: mask_r <= 32'b11111111111111111111111111111000; 5'o04: mask_r <= 32'b11111111111111111111111111110000; 5'o05: mask_r <= 32'b11111111111111111111111111100000; 5'o06: mask_r <= 32'b11111111111111111111111111000000; 5'o07: mask_r <= 32'b11111111111111111111111110000000; 5'o10: mask_r <= 32'b11111111111111111111111100000000; 5'o11: mask_r <= 32'b11111111111111111111111000000000; 5'o12: mask_r <= 32'b11111111111111111111110000000000; 5'o13: mask_r <= 32'b11111111111111111111100000000000; 5'o14: mask_r <= 32'b11111111111111111111000000000000; 5'o15: mask_r <= 32'b11111111111111111110000000000000; 5'o16: mask_r <= 32'b11111111111111111100000000000000; 5'o17: mask_r <= 32'b11111111111111111000000000000000; 5'o20: mask_r <= 32'b11111111111111110000000000000000; 5'o21: mask_r <= 32'b11111111111111100000000000000000; 5'o22: mask_r <= 32'b11111111111111000000000000000000; 5'o23: mask_r <= 32'b11111111111110000000000000000000; 5'o24: mask_r <= 32'b11111111111100000000000000000000; 5'o25: mask_r <= 32'b11111111111000000000000000000000; 5'o26: mask_r <= 32'b11111111110000000000000000000000; 5'o27: mask_r <= 32'b11111111100000000000000000000000; 5'o30: mask_r <= 32'b11111111000000000000000000000000; 5'o31: mask_r <= 32'b11111110000000000000000000000000; 5'o32: mask_r <= 32'b11111100000000000000000000000000; 5'o33: mask_r <= 32'b11111000000000000000000000000000; 5'o34: mask_r <= 32'b11110000000000000000000000000000; 5'o35: mask_r <= 32'b11100000000000000000000000000000; 5'o36: mask_r <= 32'b11000000000000000000000000000000; 5'o37: mask_r <= 32'b10000000000000000000000000000000; endcase /* * ALU */ wire [1:0] osel = {2{iralu}} & ir[13:12]; wire [1:0] qs = {2{iralu}} & ir[1:0]; wire mulnop = mul & ~q[0]; wire aluadd = divaddcond & ~a[31] | divsubcond & a[31] | mul; wire alusub = divaddcond & a[31] | divsubcond & ~a[31] | irjump | mulnop; reg alumode; reg [3:0] aluf; reg cin0; wire cin4, cin8, cin12, cin16, cin20, cin24, cin28, cin32; wire [7:0] xout; wire [7:0] yout; wire [3:0] xx; wire [3:0] yy; wire [31:0] alu; wire a_eq_m = alu == 0; always @(*) case({alusub,aluadd}) 2'b00: begin alumode <= ir[8]; aluf <= ir[7:4]; cin0 <= ir[2]; end 2'b01: begin // add M+A+C alumode <= 0; aluf <= 4'b1001; cin0 <= 0; end 2'b10: begin // sub M-A-1+C alumode <= 0; aluf <= 4'b0110; cin0 <= ~irjump; end 2'b11: begin // SETM, mul no-op alumode <= 1; aluf <= 4'b1111; cin0 <= 0; // nc end endcase alu74181 alu0( .a(m[3:0]), .b(a[3:0]), .cin(cin0), .s(aluf), .m(alumode), .f(alu[3:0]), .gout(yout[0]), .pout(xout[0]) ); alu74181 alu1( .a(m[7:4]), .b(a[7:4]), .cin(cin4), .s(aluf), .m(alumode), .f(alu[7:4]), .gout(yout[1]), .pout(xout[1]) ); alu74181 alu2( .a(m[11:8]), .b(a[11:8]), .cin(cin8), .s(aluf), .m(alumode), .f(alu[11:8]), .gout(yout[2]), .pout(xout[2]) ); alu74181 alu3( .a(m[15:12]), .b(a[15:12]), .cin(cin12), .s(aluf), .m(alumode), .f(alu[15:12]), .gout(yout[3]), .pout(xout[3]) ); alu74181 alu4( .a(m[19:16]), .b(a[19:16]), .cin(cin16), .s(aluf), .m(alumode), .f(alu[19:16]), .gout(yout[4]), .pout(xout[4]) ); alu74181 alu5( .a(m[23:20]), .b(a[23:20]), .cin(cin20), .s(aluf), .m(alumode), .f(alu[23:20]), .gout(yout[5]), .pout(xout[5]) ); alu74181 alu6( .a(m[27:24]), .b(a[27:24]), .cin(cin24), .s(aluf), .m(alumode), .f(alu[27:24]), .gout(yout[6]), .pout(xout[6]) ); alu74181 alu7( .a(m[31:28]), .b(a[31:28]), .cin(cin28), .s(aluf), .m(alumode), .f(alu[31:28]), .gout(yout[7]), .pout(xout[7]) ); cla74182 cla0(.g(yout[3:0]), .p(xout[3:0]), .cin(cin0), .coutx(cin4), .couty(cin8), .coutz(cin12), .gout(yy[0]), .pout(xx[0]) ); cla74182 cla1(.g(yout[7:4]), .p(xout[7:4]), .cin(cin16), .coutx(cin20), .couty(cin24), .coutz(cin28), .gout(yy[1]), .pout(xx[1]) ); cla74182 cla2(.g(yy), .p(xx), .cin(cin0), .coutx(cin16), .couty(cin32) ); /* * FLAGS */ reg alucarry; reg aluless; reg alusgn; reg alueq; reg pclb; wire pclbenb = iralu & funct3; wire aluneg = alu[31] & ~a_eq_m; wire [2:0] conds = ir[5] ? ir[2:0] : 0; reg conda; always @(*) case(conds) 3'o0: conda <= r[0]; 3'o1: conda <= aluneg; 3'o2: conda <= alu[31]; 3'o3: conda <= a_eq_m; 3'o4: conda <= int; 3'o5: conda <= ~vmaok; 3'o6: conda <= vmaint; 3'o7: conda <= 1; endcase wire cond = conda ^ ir[6]; wire divposlasttime = ir[7] & q[0]; wire divaddcondin = ir[6] | ~divposlasttime; wire divaddcond = div & divaddcondin; wire divsubcond = div & divposlasttime; always @(posedge clk) begin if(clkedge) begin if(iralu) begin alucarry <= ~cin32; aluless <= aluneg; alusgn <= alu[31]; alueq <= a_eq_m; end if(pclbenb) pclb <= ob[0]; end end /* * OUTPUT BUS */ reg [31:0] ob; always @(*) case(osel) 2'b00: ob <= mo; 2'b01: ob <= alu; 2'b10: ob <= {alu[31], alu[31:1]}; 2'b11: ob <= {alu[30:0], q[31]}; endcase /* * Q */ reg [31:0] q; always @(posedge clk) if(clkedge) case(qs) 2'b01: q <= {q[30:0], ~alu[31]}; 2'b10: q <= {alu[0], q[31:1]}; 2'b11: q <= ob; endcase /* * VMEMORY */ reg wmapd; reg vrdrq; reg vwrrq; reg rdrq; reg wrrq; wire readpermit = vout[19]; wire writepermit = vout[10] & vout[18]; wire mreset = RESET | 0; // TODO: ssyn wire vrdrqin = memrd | vrdrq & ~memop; wire vwrrqin = memwr | vwrrq & ~memop; wire rdrqin = vrdrq & readpermit; wire wrrqin = vwrrq & writepermit; wire readfault = vrdrq & ~readpermit; wire writefault = vwrrq & ~writepermit; wire vmaok = ~(readfault | writefault); wire memrq = rdrq | wrrq; wire mrqdlyd = memrq; // TODO: this is wrong wire mwait = mrqdlyd & memop; always @(posedge clk) begin if(mreset) begin wmapd <= 0; vrdrq <= 0; vwrrq <= 0; rdrq <= 0; wrrq <= 0; end else if(clkedge) begin wmapd <= wmap; vrdrq <= vrdrqin; vwrrq <= vwrrqin; rdrq <= rdrqin; wrrq <= wrrqin; end end wire memop = destvmamap | destvmawr | destvmard | destvma | destmemdw | destmemd | srcmemrd | destmemdmap; wire vadrenb = destvma | destvmard | destvmawr | destvmamap; wire mwdenb = destmemdw | destmemd | destmemdmap; wire srcmemrd = srcmmpx & subs0; wire memrd = destvmard; wire memwr = destmemdw | destvmawr; wire wmap = destvmamap | destmemdmap; wire mapwr0 = wmapd & ~mwd[0]; wire mapwr1 = wmapd & mwd[0]; wire vm0wp = wp & mapwr0; wire vm1wp = wp & mapwr1; wire [1:0] vms = ir[28:27]; reg [31:0] mwd; reg [31:0] vadr; reg [31:0] mrd; always @(posedge clk) begin if(clkedge) begin if(mwdenb) mwd <= ob; if(vadrenb) vadr <= ob; if(ssyn) mrd <= mdi; end end wire ssyn = 0; wire [31:0] mdi; reg [4:0] vmem1[0:'o4000-1]; wire [4:0] vmap = vmem1[vadr[22:12]]; reg [19:0] vmem2[0:'o2000-1]; wire [19:0] vout = vmem2[{vadr[11:7],vmap}]; always @(posedge clk) begin if(vm0wp) vmem1[vadr[22:12]] <= mwd[31:27]; if(vm1wp) vmem2[{vadr[11:7],vmap}] <= mwd[26:7]; end reg [31:0] mmpx; always @(*) case(vms) 2'b00: mmpx <= mrd; 2'b01: mmpx <= mwd; 2'b10: mmpx <= vadr; 2'b11: mmpx <= {vmap, vout, 5'b0, writefault, readfault}; endcase /* IR decoding for debugging */ wire ir_ilong = ir[41]; wire [1:0] ir_op = ir[40:39]; wire ir_popj = ir[38]; wire [7:0] ir_asrc = ir[37:30]; // ALU, BYTE, JUMP wire [5:0] ir_msrc = ir[29:24]; // all wire [9:0] ir_dest = ir[23:14]; // ALU, BYTE wire [1:0] ir_misc = ir[11:10]; // all wire [4:0] ir_mlen = ir[9:5]; // BYTE, DISP wire [4:0] ir_mrot = ir[4:0]; // BYTE, DISP wire [1:0] ir_alu_ob = ir[13:12]; // ALU wire [5:0] ir_alu_op = ir[9:4]; wire ir_alu_cin = ir[2]; wire [1:0] ir_alu_q = ir[1:0]; wire [7:0] ir_disp_const = ir[37:30]; // DISP wire [9:0] ir_disp_off = ir[23:14]; wire [11:0] ir_jump_npc = ir[23:12]; // JUMP wire ir_jump_r = ir[9]; wire ir_jump_p = ir[8]; wire ir_jump_n = ir[7]; wire ir_jump_inv = ir[6]; wire [5:0] ir_jump_misc = ir[5:0]; wire ir_byte_mr = ir[13]; // BYTE wire ir_byte_sr = ir[12]; endmodule