`timescale 1ns / 1ps // NW 8.10.12 rev. 26.12.2013 module RISC0( input clk, rst, input [31:0] inbus, output [5:0] ioadr, output iord, iowr, output [31:0] outbus); reg [11:0] PC; reg N, Z, C, OV; // condition flags reg [31:0] R [0:15]; // array of 16 registers reg [31:0] H; // aux register reg stall1; wire [31:0] IR; wire [31:0] pmout; wire [11:0] pcmux, nxpc; wire cond, S; wire sa, sb, sc; wire p, q, u, v, w; // instruction fields wire [3:0] op, ira, ira0, irb, irc; wire [2:0] cc; wire [15:0] imm; wire [19:0] off; wire regwr; wire [13:0] dmadr; wire dmwr, ioenb; wire [31:0] dmin, dmout; wire [1:0] sc1, sc0; // shift counts wire [31:0] A, B, C0, C1, regmux; wire [31:0] s1, s2, s3, t1, t2, t3; wire [32:0] aluRes; wire [31:0] quotient, remainder; wire [63:0] product; wire stall, stallL, stallM, stallD; wire MOV, LSL, ASR, ROR, AND, ANN, IOR, XOR; // operation signals wire ADD, SUB, MUL, DIV; wire LDR, STR, BR; PROM PM (.adr(pcmux[10:0]), .data(pmout), .clk(clk)); DRAM DM (.adr(dmadr[12:2]), .din(dmin), .dout(dmout), .we(dmwr), .clk(clk)); Multiplier1 mulUnit (.clk(clk), .run(MUL), .stall(stallM), .u(~u), .x(B), .y(C1), .z(product)); Divider divUnit (.clk(clk), .run(DIV), .stall(stallD), .x(B), .y(C1), .quot(quotient), .rem(remainder)); assign IR = pmout; // decoding assign p = IR[31]; assign q = IR[30]; assign u = IR[29]; assign v = IR[28]; assign w = IR[16]; assign cc = IR[26:24]; assign ira = IR[27:24]; assign irb = IR[23:20]; assign op = IR[19:16]; assign irc = IR[3:0]; assign imm = IR[15:0]; assign off = IR[19:0]; assign MOV = ~p & (op == 0); assign LSL = ~p & (op == 1); assign ASR = ~p & (op == 2); assign ROR = ~p & (op == 3); assign AND = ~p & (op == 4); assign ANN = ~p & (op == 5); assign IOR = ~p & (op == 6); assign XOR = ~p & (op == 7); assign ADD = ~p & (op == 8); assign SUB = ~p & (op == 9); assign MUL = ~p & (op == 10); assign DIV = ~p & (op == 11); assign LDR = p & ~q & ~u; assign STR = p & ~q & u; assign BR = p & q; assign A = R[ira0]; // register data signals assign B = R[irb]; assign C0 = R[irc]; // Arithmetic-logical unit (ALU) assign ira0 = BR ? 15 : ira; assign C1 = ~q ? C0 : {{16{v}}, imm}; assign dmadr = B[13:0] + off[13:0]; assign dmwr = STR & ~stall; assign dmin = A; assign ioenb = (dmadr[13:6] == 8'b11111111); assign iowr = STR & ioenb; assign iord = LDR & ioenb; assign ioadr = dmadr[5:0]; assign outbus = A; assign sc0 = C1[1:0]; assign sc1 = C1[3:2]; // shifter for ASR and ROR assign s1 = (sc0 == 3) ? {(w ? B[2:0] : {3{B[31]}}), B[31:3]} : (sc0 == 2) ? {(w ? B[1:0] : {2{B[31]}}), B[31:2]} : (sc0 == 1) ? {(w ? B[0] : B[31]), B[31:1]} : B; assign s2 = (sc1 == 3) ? {(w ? s1[11:0] : {12{s1[31]}}), s1[31:12]} : (sc1 == 2) ? {(w ? s1[7:0] : {8{s1[31]}}), s1[31:8]} : (sc1 == 1) ? {(w ? s1[3:0] : {4{s1[31]}}), s1[31:4]} : s1; assign s3 = C1[4] ? {(w ? s2[15:0] : {16{s2[31]}}), s2[31:16]} : s2; // shifter for LSL assign t1 = (sc0 == 3) ? {B[28:0], 3'b0} : (sc0 == 2) ? {B[29:0], 2'b0} : (sc0 == 1) ? {B[30:0], 1'b0} : B; assign t2 = (sc1 == 3) ? {t1[19:0], 12'b0} : (sc1 == 2) ? {t1[23:0], 8'b0} : (sc1 == 1) ? {t1[27:0], 4'b0} : t1; assign t3 = C1[4] ? {t2[15:0], 16'b0} : t2; assign aluRes = MOV ? (q ? (~u ? {{16{v}}, imm} : {imm, 16'b0}) : (~u ? C0 : (~v ? H : {N, Z, C, OV, 20'b0, 8'b10100000}))) : LSL ? t3 : (ASR|ROR) ? s3 : AND ? B & C1 : ANN ? B & ~C1 : IOR ? B | C1 : XOR ? B ^ C1 : ADD ? B + C1 + (u & C) : SUB ? B - C1 - (u & C) : MUL ? product[31:0] : DIV ? quotient : 0; assign regwr = ~p & ~stall | (LDR & stall1)| (BR & cond & v) ; assign regmux = (LDR & ~ioenb) ? dmout : (LDR & ioenb) ? inbus : (BR & v) ? {18'b0, nxpc, 2'b0} : aluRes; // Control unit CU assign S = N ^ OV; assign nxpc = PC + 1; assign cond = IR[27] ^ ((cc == 0) & N | // MI, PL (cc == 1) & Z | // EQ, NE (cc == 2) & C | // CS, CC (cc == 3) & OV | // VS, VC (cc == 4) & (C|Z) | // LS, HI (cc == 5) & S | // LT, GE (cc == 6) & (S|Z) | // LE, GT (cc == 7)); // T, F assign pcmux = (~rst) ? 0 : (stall) ? PC : (BR & cond & u) ? off[11:0] + nxpc : (BR & cond & ~u) ? C0[13:2] : nxpc; assign sa = aluRes[31]; assign sb = B[31]; assign sc = C1[31] ^ SUB; assign stall = stallL | stallM | stallD; assign stallL = LDR & ~stall1; always @ (posedge clk) begin PC <= pcmux; stall1 <= stallL; R[ira0] <= regwr ? regmux : A; N <= regwr ? regmux[31] : N; Z <= regwr ? (regmux[31:0] == 0) : Z; C <= (ADD|SUB) ? aluRes[32] : C; OV <= (ADD|SUB) ? (sa & ~sb & ~sc | ~sa & sb & sc) : OV; H <= MUL ? product[63:32] : DIV ? remainder : H; end endmodule