diff --git a/RTL/ALU.sv b/RTL/ALU.sv index 2824c18..e111869 100644 --- a/RTL/ALU.sv +++ b/RTL/ALU.sv @@ -21,7 +21,7 @@ module ALU #(parameter W=8)( SUB: Out = A - B; // subtract B from A ORR: Out = A | B; // bitwise OR between A and B AND: Out = A & B; // bitwise AND between A and B - LSH: Out = A << B; // shift A by B bits + LSH: Out = B << A; // shift B by A bits (limitation of control) RXOR_7: Out = ^(A[6:0]); // perform reduction XOR of lower 7 bits of A RXOR_8: Out = ^(A[7:0]); // perform reduction XOR of lower 8 bits of A XOR: Out = A ^ B; // bitwise XOR between A and B diff --git a/RTL/Ctrl.sv b/RTL/Ctrl.sv index c07b829..57bf621 100644 --- a/RTL/Ctrl.sv +++ b/RTL/Ctrl.sv @@ -1,84 +1,143 @@ -// CSE141L -import Definitions::*; +// Module Name: ALU +// Project Name: CSE141L // control decoder (combinational, not clocked) -// inputs from instrROM, ALU flags -// outputs to program_counter (fetch unit) -module Ctrl ( - input[ 8:0] Instruction, // machine code - input[ 7:0] DatMemAddr, - output logic Branch , - BranchEn , - RegWrEn , // write to reg_file (common) - MemWrEn , // write to mem (store only) - LoadInst , // mem or ALU to reg_file ? - TapSel , - Ack , // "done w/ program" - output logic[1:0] PCTarg, -// output logic[2:0] ALU_inst - ); -/* ***** All numerical values are completely arbitrary and for illustration only ***** -*/ +import Definitions::*; -// alternative -- case format -always_comb begin -// list the defaults here - Branch = 'b0; - BranchEn = 'b0; - RegWrEn = 'b1; - MemWrEn = 'b0; - LoadInst = 'b0; - TapSel ' 'b0; // - PCTarg = 'b0; // branch "where to?" - case(Instruction[8:6]) // list just the exceptions - 3'b000: begin - MemWrEn = 'b1; // store, maybe - RegWrEn = 'b0; - end - 3'b001: LoadInst = 'b1; // load - 3'b010: begin end - 3'b011: begin end - 3'b100: begin end - 3'b101: begin end - 3'b110: begin end -// no default case needed -- covered before "case" - endcase -end +module Ctrl #( + parameter W = 8, + parameter T = 10 +) ( + input logic [8:0] Instruction, + input logic [W-1:0] ALU_Out, // control ALU operation + input logic [W-1:0] RegOutA, RegOutB, // select from register inputs or immediate inputs + input logic [T-1:0] ProgCtr_p4, + input logic [W-1:0] mem_out, + output op_mne ALU_OP, + output logic [W-1:0] ALU_A, ALU_B, + output logic RegWrite, Done_in, + output logic [3:0] RaddrA, RaddrB, Waddr, RegInput, + output logic BranchEZ, BranchNZ, BranchAlways, + output logic write_mem +); -assign Ack = ProgCtr == 971; -// alternative Ack = Instruction == 'b111_000_111 + logic [7:0] I_Immediate; + logic [7:0] T_Immediate; + logic [3:0] A_operand; + logic [3:0] S_operand; + logic [3:0] G_operand; -// ALU commands -//assign ALU_inst = Instruction[2:0]; + assign I_Immediate = Instruction[7:0]; + assign T_Immediate = Instruction[2:0]; + assign A_operand = Instruction[3:0]; + assign S_operand = {'b1, Instruction[2:0]}; + assign G_operand = {'b0, Instruction[2:0]}; -// STR commands only -- write to data_memory -assign MemWrEn = Instruction[8:6]==3'b110; + assign ALU_B = RegOutB; -// all but STR and NOOP (or maybe CMP or TST) -- write to reg_file -assign RegWrEn = Instruction[8:7]!=2'b11; - -// route data memory --> reg_file for loads -// whenever instruction = 9'b110??????; -assign LoadInst = Instruction[8:6]==3'b110; // calls out load specially - -assign tapSel = LoadInst && DatMemAddr=='d62; -// jump enable command to program counter / instruction fetch module on right shift command -// equiv to simply: assign Jump = Instruction[2:0] == RSH; -always_comb - if(Instruction[2:0] == RSH) - Branch = 1; - else - Branch = 0; - -// branch every time instruction = 9'b?????1111; -assign BranchEn = &Instruction[3:0]; - -// whenever branch or jump is taken, PC gets updated or incremented from "Target" -// PCTarg = 2-bit address pointer into Target LUT (PCTarg in --> Target out -assign PCTarg = Instruction[3:2]; - -// reserve instruction = 9'b111111111; for Ack -assign Ack = &Instruction; // = ProgCtr == 385; + always_comb begin + // default values for an invalid NOP instruction, proper NOP instruction encoded as a LSH by 0 + ALU_OP = NOP; + ALU_A = RegOutA; + RegWrite = 'b1; + Done_in = 'b0; + RaddrA = 'b0; + RaddrB = 'b0; + Waddr = 'b0; + RegInput = ALU_Out; + BranchEZ = 'b0; + BranchNZ = 'b0; + BranchAlways = 'b0; + write_mem = 'b0; + casez(Instruction) + 'b1_xxxx_xxxx: begin // LDI + ALU_A = I_Immediate; + end + 'b0_0000_xxxx: begin // PUT + Waddr = A_operand; + end + 'b0_0001_xxxx: begin // GET + RaddrA = A_operand; + end + 'b0_0010_0xxx: begin // LDW + RaddrA = S_operand; + RegInput = mem_out; + end + 'b0_0010_1xxx: begin // STW + RaddrA = S_operand; + RegWrite = 'b0; + write_mem = 'b1; + end + 'b0_0011_0xxx: begin // NXT + if(S_operand == 'd8 || S_operand == 'd9 || S_operand == d'10) ALU_OP = INC; + else if (S_operand == 'd11 || S_operand == 'd12 || S_operand == d'13) ALU_OP = DEC; + else ALU_OP = NOP; + RaddrA = S_operand; + Waddr = S_operand; + end + 'b0_0011_1xxx: begin //CLB + ALU_OP = CLB; + RaddrA = G_operand; + Waddr = G_operand; + end + 'b0_0100_xxxx: begin // ADD + ALU_OP = ADD; + RaddrB = A_operand; + end + 'b0_0101_xxxx: begin // SUB + ALU_OP = SUB; + RaddrB = A_operand; + end + 'b0_0110_xxxx: begin // ORR + ALU_OP = ORR; + RaddrB = A_operand; + end + 'b0_0111_xxxx: begin // AND + ALU_OP = AND; + RaddrB = A_operand; + end + 'b0_1000_0xxx: begin // LSH + ALU_OP = LSH; + ALU_A = T_Immediate; + end + 'b0_1000_1xxx: begin // PTY + ALU_OP = RXOR_7; + RaddrA = G_operand; + end + 'b0_1001_xxxx: begin // CHK + ALU_OP = RXOR_8; + RaddrA = A_operand; + end + 'b0_1010_xxxx: begin // XOR + ALU_OP = XOR; + RaddrB = A_operand; + end + 'b0_1011_xxxx: begin // DNE + Done_in = 'b1; + end + 'b0_1110_0xxx: begin // JNZ + RegWrite = 'b0; + RaddrA = G_operand; + BranchNZ = 'b1; + end + 'b0_1110_1xxx: begin // JEZ + RegWrite = 'b0; + RaddrA = G_operand; + BranchEZ = 'b1; + end + 'b0_1111_0xxx: begin // JMP + RegWrite = 'b0; + RaddrA = G_operand; + BranchAlways = 'b1; + end + 'b0_1111_1xxx: begin // JAL + RaddrA = G_operand; + Waddr = 'd14; // write to link register specifically + RegInput = ProgCtr_p4; // write the value pc+4 + BranchAlways = 'b1; + end + endcase + end endmodule diff --git a/RTL/DataMem.sv b/RTL/DataMem.sv index 74f1b00..b7efb3a 100644 --- a/RTL/DataMem.sv +++ b/RTL/DataMem.sv @@ -1,17 +1,7 @@ -// Create Date: 2017.01.25 -// Design Name: CSE141L -// Module Name: DataMem -// Last Update: 2022.01.13 +// Module Name: ALU +// Project Name: CSE141L +// control decoder (combinational, not clocked) -// Memory can only read (LDR) or write (STR) on each Clk cycle, so there is a single -// address pointer for both read and write operations. -// -// Parameters: -// - A: Address Width. This controls the number of entries in memory -// - W: Data Width. This controls the size of each entry in memory -// This memory can hold `(2**A) * W` bits of data. -// -// WI22 is a 256-entry single-byte (8 bit) data memory. module DataMem #(parameter W=8, A=8) ( // do not change W=8 input Clk, Reset, // initialization @@ -40,10 +30,10 @@ always_ff @ (posedge Clk) if(Reset) begin // Preload desired constants into data_mem[128:255] - core[128] <= 'b1; - core[129] <= 'hff; - core[130] <= 'd64; - end + //core[128] <= 'b1; + //core[129] <= 'hff; + //core[130] <= 'd64; + end else if(WriteEn) // store // Do the actual writes core[DataAddress] <= DataIn; diff --git a/RTL/RegFile.sv b/RTL/RegFile.sv index 9be91eb..8a17c31 100644 --- a/RTL/RegFile.sv +++ b/RTL/RegFile.sv @@ -26,6 +26,8 @@ module RegFile #(parameter W=8, D=4)( // W = data path width (leave at 8); D = for(int i=0; i<2**D; i++) begin Registers[i] <= 'h0; end + Zero <= 0; + Done <= 1; // default Done to halt machine end else if (WriteEn) begin Registers[Waddr] <= DataIn;