diff --git a/RTL/ALU.sv b/RTL/ALU.sv index 9227475..2824c18 100644 --- a/RTL/ALU.sv +++ b/RTL/ALU.sv @@ -1,46 +1,32 @@ -// Module Name: ALU -// Project Name: CSE141L -// -// Additional Comments: -// combinational (unclocked) ALU +// Module Name: ALU +// Project Name: CSE141L +// Description: combinational (unclocked) ALU -// includes package "Definitions" -// be sure to adjust "Definitions" to match your final set of ALU opcodes import Definitions::*; module ALU #(parameter W=8)( - input [W-1:0] InputA, // data inputs - InputB, - input op_mne OP, // ALU opcode, part of microcode - input SC_in, // shift or carry in - output logic [W-1:0] Out, // data output - output logic Zero, // output = zero flag !(Out) - Parity, // outparity flag ^(Out) - Odd, // output odd flag (Out[0]) - SC_out // shift or carry out - // you may provide additional status flags, if desired - // comment out or delete any you don't need + input [W-1:0] A, B, // data inputs + input op_mne ALU_OP, // ALU opcode, part of microcode + output logic [W-1:0] Out, // data output + output logic Zero // zero flag ); -always_comb begin -// No Op = default -// add desired ALU ops, delete or comment out any you don't need - Out = 8'b0; // don't need NOOP? Out = 8'bx - SC_out = 1'b0; // will flag any illegal opcodes - case(OP) - ADD : {SC_out,Out} = InputA + InputB + SC_in; // unsigned add with carry-in and carry-out - LSH : {SC_out,Out} = {InputA[7:0],SC_in}; // shift left, fill in with SC_in, fill SC_out with InputA[7] -// for logical left shift, tie SC_in = 0 - RSH : {Out,SC_out} = {SC_in, InputA[7:0]}; // shift right - XOR : Out = InputA ^ InputB; // bitwise exclusive OR - AND : Out = InputA & InputB; // bitwise AND - SUB : {SC_out,Out} = InputA + (~InputB) + 1; // InputA - InputB; - CLR : {SC_out,Out} = 'b0; - endcase -end - -assign Zero = ~|Out; // reduction NOR Zero = !Out; -assign Parity = ^Out; // reduction XOR -assign Odd = Out[0]; // odd/even -- just the value of the LSB - + always_comb begin + case(ALU_OP) + NOP: Out = A; // pass A to out + INC: Out = A + 1; // imcrement A by 1 + DEC: Out = A - 1; // decrement A by 1 + CLB: Out = {1'b0, A[6:0]}; // set MSB of A to 0 + ADD: Out = A + B; // add A to B + 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 + 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 + default: Out = 'bx; // flag illegal ALU_OP values + endcase + Zero = Out == 0; + end endmodule diff --git a/RTL/Definitions.sv b/RTL/Definitions.sv index 0be773b..ad68108 100644 --- a/RTL/Definitions.sv +++ b/RTL/Definitions.sv @@ -1,16 +1,22 @@ -//This file defines the parameters used in the alu -// CSE141L -// Rev. 2022.5.27 -// import package into each module that needs it -// packages very useful for declaring global variables -// need > 8 instructions? -// typedef enum logic[3:0] and expand the list of enums -package Definitions; - -// enum names will appear in timing diagram -// ADD = 3'b000; LSH = 3'b001; etc. 3'b111 is undefined here - typedef enum logic[2:0] { - ADD, LSH, RSH, XOR, - AND, SUB, CLR } op_mne; +// Module Name: ALU +// Project Name: CSE141L +// Description: contains enumerated ALU operations + +package Definitions; + + typedef enum logic[3:0] { + NOP, // perform a simple value passthrough + INC, // increment by 1 + DEC, // decrement by 1 + CLB, // clear leading bit + ADD, // addition + SUB, // subtraction + ORR, // bitwise OR + AND, // bitwise AND + LSH, // left shift + RXOR_7, // reduction XOR with lower 7 bits + RXOR_8, // reduction XOR with lower 8 bits + XOR // bitwise XOR + } op_mne; -endpackage // definitions +endpackage // definitions diff --git a/RTL/Immediate_LUT.sv b/RTL/Immediate_LUT.sv deleted file mode 100644 index 498c966..0000000 --- a/RTL/Immediate_LUT.sv +++ /dev/null @@ -1,26 +0,0 @@ -/* CSE141L - possible lookup table for PC target - leverage a few-bit pointer to a wider number - Lookup table acts like a function: here Target = f(Addr); - in general, Output = f(Input); lots of potential applications -*/ -module Immediate_LUT #(PC_width = 10)( - input [ 2:0] addr, - output logic[PC_width-1:0] datOut - ); - -always_comb begin - datOut = 'h001; // default to 1 (or PC+1 for relative) - case(addr) - 2'b00: datOut = 'hfc; // -4, i.e., move back 16 lines of machine code - 2'b01: datOut = 'h03; - 2'b10: datOut = 'h07; - endcase -end - -endmodule - - - // 3fc = 1111111100 -4 - // PC 0000001000 8 - // 0000000100 4 \ No newline at end of file diff --git a/RTL/InstFetch.sv b/RTL/InstFetch.sv index 2e9e56d..1c60605 100644 --- a/RTL/InstFetch.sv +++ b/RTL/InstFetch.sv @@ -1,37 +1,24 @@ -// Design Name: basic_proc -// Module Name: InstFetch -// Project Name: CSE141L -// Description: instruction fetch (pgm ctr) for processor -// -// Revision: 2021.11.27 -// Suggested ProgCtr width 10 t0 12 bits -module InstFetch #(parameter T=10)( // PC width -- up to 32, if you like - input Reset, // reset, init, etc. -- force PC to 0 - Start, // begin next program in series (request issued by test bench) - Clk, // PC can change on pos. edges only - BranchAbs, // jump conditionally to Target value - BranchRelEn, // jump conditionally to Target + PC - ALU_flag, // flag from ALU, e.g. Zero, Carry, Overflow, Negative (from ARM) - input [T-1:0] Target, // jump ... "how high?" - output logic [T-1:0] ProgCtr // the program counter register itself - ); - -// you may wish to use either absolute or relative branching -// you may use both, but you will need appropriate control bits -// branch/jump is how we handle gosub and return to main -// program counter can clear to 0, increment, or branch -// for unconditional branching, "ALU_flag" input should be driven by 1 - always_ff @(posedge Clk) // or just always; always_ff is a linting construct - if(Reset) - ProgCtr <= 0; // for first program; want different value for 2nd or 3rd - else if(Start) // hold while start asserted; commence when released - ProgCtr <= 0; //or <= ProgCtr; holds at starting value - else if(BranchAbs && ALU_flag // unconditional absolute jump - ProgCtr <= Target; // how would you make it conditional and/or relative? - else if(BranchRelEn && ALU_flag) // conditional relative jump - ProgCtr <= Target + ProgCtr; // how would you make it unconditional and/or absolute - else - ProgCtr <= ProgCtr+'b1; // default increment (no need for ARM/MIPS +4 -- why?) +// Module Name: ALU +// Project Name: CSE141L +// Description: instruction fetch (pgm ctr) for processor -endmodule - +module InstFetch #(parameter T=10, parameter W=8)( // T is PC address size, W is the jump target pointer width, which is less + input logic Clk, Reset, // clock, reset + input logic BranchEZ, BranchNZ, BranchAlways, Zero, // branch control signals zero from alu signals; brnahc signals will be one hot encoding + input logic done // Done flag to indicate if the PC should increment at all + input logic [W-1:0] Target, // jump target pointer + output logic [T-1:0] ProgCtr_p4 // value of pc+4 for use in JAL instruction itself +); + + logic [T-1:0] PC; + + always_ff @(posedge Clk) begin + if(Reset) PC <= 0; // if reset, set PC to 0 + else if (BranchAlways) PC <= Target; // if unconditional branch, assign PC to target + else if (BranchEZ && Zero) PC <= Target; // if branch on zero and zero is true, then assign PC to target + else if (BranchNZ && !Zero) PC <= Target; // if branch on non zero and zero is false, then assign PC to parget + else if (!done) PC <= PC + 'b1; // if not a branch but CPU is not done, then + else PC <= PC; + end + +endmodule \ No newline at end of file diff --git a/RTL/RegFile.sv b/RTL/RegFile.sv index 9586f08..9be91eb 100644 --- a/RTL/RegFile.sv +++ b/RTL/RegFile.sv @@ -1,46 +1,37 @@ -// Create Date: 2019.01.25 -// Design Name: CSE141L -// Module Name: reg_file -// Revision: 2022.05.04 -// Additional Comments: allows preloading with user constants -// This version is fully synthesizable and highly recommended. - -/* parameters are compile time directives - this can be an any-width, any-depth reg_file: just override the params! -*/ -module RegFile #(parameter W=8, D=4)( // W = data path width (leave at 8); D = address pointer width - input Clk, - Reset, // note use of Reset port - WriteEn, - input [D-1:0] RaddrA, // address pointers - RaddrB, - Waddr, - input [W-1:0] DataIn, - output [W-1:0] DataOutA, // showing two different ways to handle DataOutX, for - output logic [W-1:0] DataOutB // pedagogic reasons only - ); - -// W bits wide [W-1:0] and 2**4 registers deep -logic [W-1:0] Registers[2**D]; // or just registers[16] if we know D=4 always +// Module Name: ALU +// Project Name: CSE141L +// Description: register file -// combinational reads -/* can use always_comb in place of assign - difference: assign is limited to one line of code, so - always_comb is much more versatile -*/ -assign DataOutA = Registers[RaddrA]; // assign & always_comb do the same thing here -always_comb DataOutB = Registers[RaddrB]; // can read from addr 0, just like ARM - -// sequential (clocked) writes -always_ff @ (posedge Clk) - if (Reset) begin - for(int i=0; i<2**D; i++) - Registers[i] <= 'h0; -// we can override this universal clear command with desired initialization values - Registers[0] <= 'd30; // loads 30 (=0x1E) into RegFile address 0 - Registers[2] <= 'b101; // loads 00000101 into RegFile address 2 - end - else if (WriteEn) // works just like data_memory writes - Registers[Waddr] <= DataIn; +module RegFile #(parameter W=8, D=4)( // W = data path width (leave at 8); D = address pointer width + input Clk, Reset, WriteEn, + input [D-1:0] RaddrA, RaddrB, Waddr, // read anad write address pointers + input [W-1:0] DataIn, // data to be written + input Zero_in, Done_in, // since flags are stored in register file, need this as an input + output logic [W-1:0] DataOutA, DataOutB, // data to read out + output logic Zero_out, Done_out // output of zero and done flags +); + + logic [W-1:0] Registers[2**D]; // 2^D registers of with W + logic Zero, Done; + + // combination read + assign DataOutA = Registers[RaddrA]; + assign DataOutB = Registers[RaddrB]; + assign Zero_out = Zero; + assign Done_out = Done; + + // sequential (clocked) writes + always_ff @ (posedge Clk) begin + if (Reset) begin // reset all registers to 0 when reset + for(int i=0; i<2**D; i++) begin + Registers[i] <= 'h0; + end + end + else if (WriteEn) begin + Registers[Waddr] <= DataIn; + Zero <= Zero_in; + Done <= Done_in; + end + end endmodule diff --git a/RTL/dummy_DUT.sv b/RTL/top_level.sv similarity index 100% rename from RTL/dummy_DUT.sv rename to RTL/top_level.sv diff --git a/.devcontainer/Dockerfile b/firmware/.devcontainer/Dockerfile similarity index 100% rename from .devcontainer/Dockerfile rename to firmware/.devcontainer/Dockerfile diff --git a/.devcontainer/devcontainer.json b/firmware/.devcontainer/devcontainer.json similarity index 100% rename from .devcontainer/devcontainer.json rename to firmware/.devcontainer/devcontainer.json diff --git a/.devcontainer/requirements.txt b/firmware/.devcontainer/requirements.txt similarity index 100% rename from .devcontainer/requirements.txt rename to firmware/.devcontainer/requirements.txt diff --git a/firmware/program1.asm b/firmware/program1.asm index ed21b1a..1c949ef 100644 --- a/firmware/program1.asm +++ b/firmware/program1.asm @@ -60,7 +60,6 @@ lfsr_routine: GET r7 // get previous state PUT r7 // put next state to r7 GET r14 // load link register JMP r0 // return to function call address -done: LDI #b10000000 // load the processor flag state needed to halt the program - PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished +done: DNE // flag the CPU as done LDI #d255 JMP r0 \ No newline at end of file diff --git a/firmware/program2.asm b/firmware/program2.asm index c82202d..39bbca3 100644 --- a/firmware/program2.asm +++ b/firmware/program2.asm @@ -101,7 +101,6 @@ lfsr_routine: GET r7 // get previous state PUT r7 // put next state to r7 GET r14 // load link register JMP r0 // return to function call address -done: LDI #b10000000 // load the processor flag state needed to halt the program - PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished +done: DNE // flag the CPU as done LDI #d255 JMP r0 \ No newline at end of file diff --git a/firmware/program3.asm b/firmware/program3.asm index adda2b6..53f210c 100644 --- a/firmware/program3.asm +++ b/firmware/program3.asm @@ -109,7 +109,6 @@ lfsr_routine: GET r7 // get previous state PUT r7 // put next state to r7 GET r14 // load link register JMP r0 // return to function call address -done: LDI #b10000000 // load the processor flag state needed to halt the program - PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished +done: DNE // flag the CPU as done LDI #d255 JMP r0 \ No newline at end of file