push last commit
This commit is contained in:
parent
a659abea2a
commit
2f967bef04
64
RTL/ALU.sv
64
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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
Reference in New Issue
Block a user