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
|
// Module Name: ALU
|
||||||
// Project Name: CSE141L
|
// Project Name: CSE141L
|
||||||
//
|
// Description: combinational (unclocked) ALU
|
||||||
// Additional Comments:
|
|
||||||
// combinational (unclocked) ALU
|
|
||||||
|
|
||||||
// includes package "Definitions"
|
|
||||||
// be sure to adjust "Definitions" to match your final set of ALU opcodes
|
|
||||||
import Definitions::*;
|
import Definitions::*;
|
||||||
|
|
||||||
module ALU #(parameter W=8)(
|
module ALU #(parameter W=8)(
|
||||||
input [W-1:0] InputA, // data inputs
|
input [W-1:0] A, B, // data inputs
|
||||||
InputB,
|
input op_mne ALU_OP, // ALU opcode, part of microcode
|
||||||
input op_mne OP, // ALU opcode, part of microcode
|
output logic [W-1:0] Out, // data output
|
||||||
input SC_in, // shift or carry in
|
output logic Zero // zero flag
|
||||||
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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
// No Op = default
|
case(ALU_OP)
|
||||||
// add desired ALU ops, delete or comment out any you don't need
|
NOP: Out = A; // pass A to out
|
||||||
Out = 8'b0; // don't need NOOP? Out = 8'bx
|
INC: Out = A + 1; // imcrement A by 1
|
||||||
SC_out = 1'b0; // will flag any illegal opcodes
|
DEC: Out = A - 1; // decrement A by 1
|
||||||
case(OP)
|
CLB: Out = {1'b0, A[6:0]}; // set MSB of A to 0
|
||||||
ADD : {SC_out,Out} = InputA + InputB + SC_in; // unsigned add with carry-in and carry-out
|
ADD: Out = A + B; // add A to B
|
||||||
LSH : {SC_out,Out} = {InputA[7:0],SC_in}; // shift left, fill in with SC_in, fill SC_out with InputA[7]
|
SUB: Out = A - B; // subtract B from A
|
||||||
// for logical left shift, tie SC_in = 0
|
ORR: Out = A | B; // bitwise OR between A and B
|
||||||
RSH : {Out,SC_out} = {SC_in, InputA[7:0]}; // shift right
|
AND: Out = A & B; // bitwise AND between A and B
|
||||||
XOR : Out = InputA ^ InputB; // bitwise exclusive OR
|
LSH: Out = A << B; // shift A by B bits
|
||||||
AND : Out = InputA & InputB; // bitwise AND
|
RXOR_7: Out = ^(A[6:0]); // perform reduction XOR of lower 7 bits of A
|
||||||
SUB : {SC_out,Out} = InputA + (~InputB) + 1; // InputA - InputB;
|
RXOR_8: Out = ^(A[7:0]); // perform reduction XOR of lower 8 bits of A
|
||||||
CLR : {SC_out,Out} = 'b0;
|
XOR: Out = A ^ B; // bitwise XOR between A and B
|
||||||
endcase
|
default: Out = 'bx; // flag illegal ALU_OP values
|
||||||
end
|
endcase
|
||||||
|
Zero = Out == 0;
|
||||||
assign Zero = ~|Out; // reduction NOR Zero = !Out;
|
end
|
||||||
assign Parity = ^Out; // reduction XOR
|
|
||||||
assign Odd = Out[0]; // odd/even -- just the value of the LSB
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
//This file defines the parameters used in the alu
|
// Module Name: ALU
|
||||||
// CSE141L
|
// Project Name: CSE141L
|
||||||
// Rev. 2022.5.27
|
// Description: contains enumerated ALU operations
|
||||||
// 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;
|
package Definitions;
|
||||||
|
|
||||||
// enum names will appear in timing diagram
|
typedef enum logic[3:0] {
|
||||||
// ADD = 3'b000; LSH = 3'b001; etc. 3'b111 is undefined here
|
NOP, // perform a simple value passthrough
|
||||||
typedef enum logic[2:0] {
|
INC, // increment by 1
|
||||||
ADD, LSH, RSH, XOR,
|
DEC, // decrement by 1
|
||||||
AND, SUB, CLR } op_mne;
|
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: ALU
|
||||||
// Module Name: InstFetch
|
// Project Name: CSE141L
|
||||||
// Project Name: CSE141L
|
// Description: instruction fetch (pgm ctr) for processor
|
||||||
// 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
|
module InstFetch #(parameter T=10, parameter W=8)( // T is PC address size, W is the jump target pointer width, which is less
|
||||||
// you may use both, but you will need appropriate control bits
|
input logic Clk, Reset, // clock, reset
|
||||||
// branch/jump is how we handle gosub and return to main
|
input logic BranchEZ, BranchNZ, BranchAlways, Zero, // branch control signals zero from alu signals; brnahc signals will be one hot encoding
|
||||||
// program counter can clear to 0, increment, or branch
|
input logic done // Done flag to indicate if the PC should increment at all
|
||||||
// for unconditional branching, "ALU_flag" input should be driven by 1
|
input logic [W-1:0] Target, // jump target pointer
|
||||||
always_ff @(posedge Clk) // or just always; always_ff is a linting construct
|
output logic [T-1:0] ProgCtr_p4 // value of pc+4 for use in JAL instruction itself
|
||||||
if(Reset)
|
);
|
||||||
ProgCtr <= 0; // for first program; want different value for 2nd or 3rd
|
|
||||||
else if(Start) // hold while start asserted; commence when released
|
logic [T-1:0] PC;
|
||||||
ProgCtr <= 0; //or <= ProgCtr; holds at starting value
|
|
||||||
else if(BranchAbs && ALU_flag // unconditional absolute jump
|
always_ff @(posedge Clk) begin
|
||||||
ProgCtr <= Target; // how would you make it conditional and/or relative?
|
if(Reset) PC <= 0; // if reset, set PC to 0
|
||||||
else if(BranchRelEn && ALU_flag) // conditional relative jump
|
else if (BranchAlways) PC <= Target; // if unconditional branch, assign PC to target
|
||||||
ProgCtr <= Target + ProgCtr; // how would you make it unconditional and/or absolute
|
else if (BranchEZ && Zero) PC <= Target; // if branch on zero and zero is true, then assign PC to target
|
||||||
else
|
else if (BranchNZ && !Zero) PC <= Target; // if branch on non zero and zero is false, then assign PC to parget
|
||||||
ProgCtr <= ProgCtr+'b1; // default increment (no need for ARM/MIPS +4 -- why?)
|
else if (!done) PC <= PC + 'b1; // if not a branch but CPU is not done, then
|
||||||
|
else PC <= PC;
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -1,46 +1,37 @@
|
|||||||
// Create Date: 2019.01.25
|
// Module Name: ALU
|
||||||
// Design Name: CSE141L
|
// Project Name: CSE141L
|
||||||
// Module Name: reg_file
|
// Description: register 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
|
module RegFile #(parameter W=8, D=4)( // W = data path width (leave at 8); D = address pointer width
|
||||||
input Clk,
|
input Clk, Reset, WriteEn,
|
||||||
Reset, // note use of Reset port
|
input [D-1:0] RaddrA, RaddrB, Waddr, // read anad write address pointers
|
||||||
WriteEn,
|
input [W-1:0] DataIn, // data to be written
|
||||||
input [D-1:0] RaddrA, // address pointers
|
input Zero_in, Done_in, // since flags are stored in register file, need this as an input
|
||||||
RaddrB,
|
output logic [W-1:0] DataOutA, DataOutB, // data to read out
|
||||||
Waddr,
|
output logic Zero_out, Done_out // output of zero and done flags
|
||||||
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]; // 2^D registers of with W
|
||||||
logic [W-1:0] Registers[2**D]; // or just registers[16] if we know D=4 always
|
logic Zero, Done;
|
||||||
|
|
||||||
// combinational reads
|
// combination read
|
||||||
/* can use always_comb in place of assign
|
assign DataOutA = Registers[RaddrA];
|
||||||
difference: assign is limited to one line of code, so
|
assign DataOutB = Registers[RaddrB];
|
||||||
always_comb is much more versatile
|
assign Zero_out = Zero;
|
||||||
*/
|
assign Done_out = Done;
|
||||||
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
|
// sequential (clocked) writes
|
||||||
always_ff @ (posedge Clk)
|
always_ff @ (posedge Clk) begin
|
||||||
if (Reset) begin
|
if (Reset) begin // reset all registers to 0 when reset
|
||||||
for(int i=0; i<2**D; i++)
|
for(int i=0; i<2**D; i++) begin
|
||||||
Registers[i] <= 'h0;
|
Registers[i] <= 'h0;
|
||||||
// we can override this universal clear command with desired initialization values
|
end
|
||||||
Registers[0] <= 'd30; // loads 30 (=0x1E) into RegFile address 0
|
end
|
||||||
Registers[2] <= 'b101; // loads 00000101 into RegFile address 2
|
else if (WriteEn) begin
|
||||||
end
|
Registers[Waddr] <= DataIn;
|
||||||
else if (WriteEn) // works just like data_memory writes
|
Zero <= Zero_in;
|
||||||
Registers[Waddr] <= DataIn;
|
Done <= Done_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -60,7 +60,6 @@ lfsr_routine: GET r7 // get previous state
|
|||||||
PUT r7 // put next state to r7
|
PUT r7 // put next state to r7
|
||||||
GET r14 // load link register
|
GET r14 // load link register
|
||||||
JMP r0 // return to function call address
|
JMP r0 // return to function call address
|
||||||
done: LDI #b10000000 // load the processor flag state needed to halt the program
|
done: DNE // flag the CPU as done
|
||||||
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
|
|
||||||
LDI #d255
|
LDI #d255
|
||||||
JMP r0
|
JMP r0
|
@ -101,7 +101,6 @@ lfsr_routine: GET r7 // get previous state
|
|||||||
PUT r7 // put next state to r7
|
PUT r7 // put next state to r7
|
||||||
GET r14 // load link register
|
GET r14 // load link register
|
||||||
JMP r0 // return to function call address
|
JMP r0 // return to function call address
|
||||||
done: LDI #b10000000 // load the processor flag state needed to halt the program
|
done: DNE // flag the CPU as done
|
||||||
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
|
|
||||||
LDI #d255
|
LDI #d255
|
||||||
JMP r0
|
JMP r0
|
@ -109,7 +109,6 @@ lfsr_routine: GET r7 // get previous state
|
|||||||
PUT r7 // put next state to r7
|
PUT r7 // put next state to r7
|
||||||
GET r14 // load link register
|
GET r14 // load link register
|
||||||
JMP r0 // return to function call address
|
JMP r0 // return to function call address
|
||||||
done: LDI #b10000000 // load the processor flag state needed to halt the program
|
done: DNE // flag the CPU as done
|
||||||
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
|
|
||||||
LDI #d255
|
LDI #d255
|
||||||
JMP r0
|
JMP r0
|
Reference in New Issue
Block a user