push last commit

This commit is contained in:
Arthur Lu 2022-08-13 16:36:00 -07:00
parent a659abea2a
commit 2f967bef04
12 changed files with 106 additions and 165 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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