design a pipelined CPU using Verilog HDL. i have all the components (.v files) created. Just need help connecting them with a testbench and knowing how to demonstrate the sum instruction
Details in s13prjt
Des
i
g
n
a
Structural Model of a Pipelined CPU
The final project is to design a structural model of a pipelined CPU with
1
3 instructions using Verilog HDL.
Description:
In this project, you are asked to design a 32-bit pipelined CPU for the given Instruction Set
A
rchitecture (ISA). The ISA is described below.
· Register file size: 64 registers, each register has 32 bits.
· PC: 32 bits
· Instruction format: Each instruction is 32-bit wide, and consists of five fields: opcode, rd, rs, rt, and unused. The format is as follows.
Opcode (4 bits) |
rd (6 bits) |
rs (6 bits) |
rt (6 bits) |
unused(1
0 bits) |
The 13 instructions are defined in following table.
Instruction
Symbol
Opcode
rd
rs
rt
Function
No operation
NOP
0000
x
x
x
No operation
Load PC
LDPC rd
1111
rd
x
x
$rd ( M[PC]
Load
LD rd, rs
1110
rd
rs
x
$rd ( M[$rs]
Store
ST rd, rs
0011
x
rs
rt
M[$rs] ( $rt
Add
ADD
rd, rs, rt
0100
rd
rs
rt
$rd ( $rs + $rt
Increment
INC
rd, rs
0101
rd
rs
x
$rd ( $rs + 1
Negate
NEG
rd, rs
0110
rd
rs
x
$rd ( -$rs
Subtract
SUB
rd, rs, rt
0111
rd
rs
rt
$rd ( $rs – $rt
Jump
J rs
1000
x
rs
x
PC ( $rs
Branch if zero
BRZ rs
1001
x
rs
x
PC ( $rs, if Z
=
1
Jump memory
JM rs
1010
x
rs
x
PC ( M[$rs]
Branch if negative
BRN rs
1011
x
rs
x
PC ( $rs, if N = 1
Sum
SUM, rd, rs, rt
0001
rd
rs
rt
$1
[$]
rt
i
rdmemoryrsi
–
=
=+
å
Also, use the instructions in the ISA to code the computation of finding the sum of n numbers.
(1)
A=
n
i
i
a
=
å
You can create your new instructions to make the above coding easier. This computation will be used to test your CPU. You may not need five stages in your pipeline.
When you analyze the cycle time, you can use the following delay data: delay of memory (I and D memory): 2 ns., delay of register file: 1.5 ns., delay of ALU (
add
ers): 2 ns. Ignore the delays of all other components.
Submission:
1. Report
a. Please submit a written report, including the following
· abstract (short description or outline of the project),
· detailed description of the CPU design including the datapath and the truth table of your control.
· test benchmarks/waveforms verifying the functions,
· assembly code for calculating the sum in (1).
· estimate the time need to execute your code for (1) based on your CPU design, and verify your estimate with simulation/waveform.
2. Demo: You will demo your working programs to our TA. During the demo, the TA will provide you n random numbers and you will show the TA the result after running your program on your pipeline. You will also be asked to perform random but related tasks (for instance, change the address of data and demo the modified program), and be prepared to answer related project questions. The purpose of these questions is to make sure that you understand the project thoroughly.
ALU Truth Table
ADD
INC
NEG
SU
B
OUT
Operation
1
0
0
0
B+
A
1
0
0
B+1
increment
0
1
0
-A
2’s complement
0
0
1
B-A
subtract
0
0
0
don’t care
no operation
1
1
1
Pass A
32
32
32
Z
N
A
B
ALU Block Diagram
_1429604802.unknown
_1156935698.unknown
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:43:20 04/08/2013
// Design Name:
// Module Name: Adder
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Adder(
input [31:0] A,
input [31:0] B,
output [31:0] Y
);
assign Y = A + B;
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:41:22 05/21/2013
// Design Name:
// Module Name: ALU
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ALU(
input [31:0] IN1,
input [31:0] IN2,
input [3:0] ALUControl,
output reg [31:0] OUT,
output reg Zero,
output reg Negative
);
always @(IN1 or IN2 or ALUControl) begin
// Add
if(ALUControl == 8)
OUT = IN1 + IN2;
// Increment
else if(ALUControl == 4)
OUT = IN1 + 1;
// Negative
else if(ALUControl == 2)
OUT = -IN1;
// Subtract
else if(ALUControl == 1)
OUT = IN1 – IN2;
// Pass A
else
OUT = IN1;
end
assign Zero = (OUT==0)? 1:0;
assign Negative = (OUT<0) ? 1:0;
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 16:08:56 06/01/2013
// Design Name:
// Module Name: Control
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Control(
input [3:0] OpCode,
output reg [3:0] ALUControl, // ALU
output reg MemWrite, // Data Mem
output reg MemRead, // Data Mem
output reg Jump, // Jump Mux
output reg JumpMem, // Jump Mem Mux
output reg BifZ, // Branch if Zero AND
output reg BifN, // Branch if Neg AND
output reg LoadPC, // RS/PC Mux
output reg RegWrite // Reg
);
always @(OpCode) begin
// Long “if” statement to go through opcode
if(OpCode == 0) begin // No operation
ALUControl = 0;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else if(OpCode == 15) begin // Load PC
ALUControl = 15;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 1;
RegWrite = 1;
end
else if(OpCode == 14) begin // Load
ALUControl = 15;
MemWrite = 0;
MemRead = 1;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 3) begin // Store
ALUControl = 15;
MemWrite = 1;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else if(OpCode == 4) begin // Add
ALUControl = 8;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 5) begin // Increment
ALUControl = 4;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 6) begin // Negate
ALUControl = 2;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 7) begin // Subtract
ALUControl = 1;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 8) begin // Jump
ALUControl = 0;
MemWrite = 0;
MemRead = 0;
Jump = 1;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else if(OpCode == 9) begin // Branch if Zero
ALUControl = 15;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 1;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else if(OpCode == 10) begin // Jump Memory
ALUControl = 15;
MemWrite = 0;
MemRead = 1;
Jump = 0;
JumpMem = 1;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else if(OpCode == 11) begin // Branch if Negative
ALUControl = 15;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 1;
end
else if(OpCode == 1) begin // Sum
ALUControl = 0;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
else
ALUControl = 0;
MemWrite = 0;
MemRead = 0;
Jump = 0;
JumpMem = 0;
BifZ = 0;
BifN = 0;
LoadPC = 0;
RegWrite = 0;
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:58:19 04/30/2013
// Design Name:
// Module Name: InstFetch
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module InstFetch(
input clock,
input reset,
output [31:0] instruction
);
wire [31:0] X;
wire [31:0] Y;
PC A1 (.in(X), .clock(clock), .out(Y));
InstMem A2 (.PC(Y), .clock(clock), .inst(instruction));
Adder A3 (.A(Y), .B(4), .Y(X));
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:06:44 04/30/2013
// Design Name:
// Module Name: InstMem
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module InstMem(
input [31:0] PC,
input clock,
output reg [31:0] inst
);
reg[31:0] mem[1023:0];
initial begin
$readmemb(“instruction.txt”, mem);
end
always @(posedge clock) begin
inst = mem[PC];
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:21:36 06/01/2013
// Design Name:
// Module Name: JumpOrBranch
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module JumpOrBranch(
input [31:0] PC,
input BifN,
input Neg,
input BifZ,
input Zero,
input J,
input JM,
input [31:0] RegValue,
input [31:0] MemValue,
output reg [31:0] NewPC
);
always @(PC) begin
if(J == 1) // Check if Jump
NewPC = RegValue;
else if(BifN & Neg) // Check if Negative and Branch
NewPC = RegValue;
else if(BifZ & Zero) // Check if Zero and Branch
NewPC = RegValue;
else if(JM == 1) // Check if Jump Memory
NewPC = MemValue;
else
NewPC = PC; // Reg. PC + 4
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:08:25 04/23/2013
// Design Name:
// Module Name: PC
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module PC(
input [31:0] in,
input clock,
output reg [31:0] out
);
initial begin
out = 0;
end
always @(posedge clock) begin // when clock edge is positive, set ‘out’ equal to ‘in’
out = in;
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:34:17 06/01/2013
// Design Name:
// Module Name: Pipeline
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Pipeline(
input clock,
input reset,
output [31:0] instruction
);
wire [31:0] inPC;
wire [31:0] outPC;
wire [31:0] AddedPC; // PC + 4 Result
wire [31:0] InstFromMem;
wire [31:0] RegData1;
wire [31:0] RegData2;
wire [31:0] MemFromData;
wire [31:0] MemOrReg; // Result from mux
wire [31:0] PCorReg; // Result from mux
wire [31:0] ALUOut; // Result from ALU
wire [3:0] ALUSrc; // Control
wire [0:0] MW; // Control
wire [0:0] MR; // Control
wire [0:0] J; // Control
wire [0:0] JM; // Control
wire [0:0] BZ; // Control
wire [0:0] BN; // Control
wire [0:0] LPC; // Control
wire [0:0] RW; // Control
wire [0:0] Z; // ALU Result – Zero
wire [0:0] N; // ALU Result – Negative
PC A1 (.in(inPC),
.clock(clock),
.out(outPC));
InstMem A2 (.PC(outPC),
.clock(clock),
.inst(InstFromMem));
Control A3 (.OpCode(InstFromMem[31:28]),
.ALUControl(ALUSrc),
.MemWrite(MW),
.MemRead(MR),
.Jump(J),
.JumpMem(JM),
.BifZ(BZ),
.BifN(BN),
.LoadPC(LPC),
.RegWrite(RW));
RegMem A4 (.RdReg1(InstFromMem[21:16]),
.RdReg2(InstFromMem[15:10]),
.DestReg(InstFromMem[27:22]),
.clock(clock),
.RegWrite(RW),
.RdData1(RegData1),
.RdData2(RegData2),
.WriteData(MemOrReg));
TwoToOneMux A5 (.Selector(LPC),
.A(RegData1),
.B(outPC),
.Out(PCorReg));
ALU A6 (.IN1(PCorReg),
.IN2(RegData2),
.ALUControl(ALUSrc),
.OUT(ALUOut),
.Negative(N),
.Zero(Z));
DataMemory A7 (.address(PCorReg),
.writedata(RegData2),
.memwrite(MW),
.memread(MR),
.clock(clock),
.readdata(MemFromData));
TwoToOneMux A8 (.Selector(MR),
.A(ALUOut),
.B(MemFromData),
.Out(MemorReg));
Adder A9 (.A(outPC),
.B(4),
.Y(AddedPC));
JumpOrBranch A10 (.PC(outPC),
.BifZ(BZ),
.BifN(BN),
.Neg(N),
.Zero(Z),
.J(J),
.JM(JM),
.RegValue(RegData1),
.MemValue(MemFromData),
.NewPC(inPC));
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:32:16 05/21/2013
// Design Name:
// Module Name: RegMem
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module RegMem(
input [5:0] RdReg1,
input [5:0] RdReg2,
input [5:0] DestReg,
input [31:0] WriteData,
input clock,
input RegWrite,
output reg [31:0] RdData1,
output reg [31:0] RdData2
);
reg[31:0] registers[2047:0];
initial begin
$readmemb(“registers.txt”, registers);
end
always @(posedge clock) begin
RdData1 = registers[RdReg1];
RdData2 = registers[RdReg2];
end
always @(negedge clock) begin
if(RegWrite == 1) begin
registers[DestReg] = WriteData;
end
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:52:25 06/01/2013
// Design Name:
// Module Name: TwoToOneMux
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module TwoToOneMux(
input Selector,
input [31:0] A,
input [31:0] B,
output reg [31:0] Out
);
always @(A or B or Selector) begin // A if 0
if(Selector == 0) // B if 1
Out = A;
else
Out = B;
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:25:31 04/23/2013
// Design Name:
// Module Name: DataMemory
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 – File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module DataMemory(
input [31:0] address,
input [31:0] writedata,
input memwrite,
input memread,
input clock,
output reg [31:0] readdata
);
// address = reg 1
// writedata = reg 2
// readdata = destination reg
reg[31:0] memory[255:0];
// to split between memread and memwrite, have memwrite on posedge and memread on negedge
always @(posedge clock) begin // write memory, only if memwrite is 1
if(memwrite == 1) begin
memory[address] = writedata;
end
end
always @(negedge clock) begin // read memory, only if memread is 1
if(memread == 1) begin
readdata = memory[address];
end
end
endmodule
For the project demos, be prepared with your testbench and memory array values to implement the sum instruction. So prepare a testbench, load your instruction memory with the sum instruction, load your data memory with 4 values 2 3 5 and -7. Thus the value of N will be 4 in this case. Later when I ask you to demo with different values all you will need to do is make changes in your instruction and data memory.