lab 4 final report
TRANSCRIPT
Laboratory #4:The Simple Processor
Kyle Villano, Tim Kindervatter and Ian Patel
ELC 363-02Dr. Jesson
The College of New JerseyNovember 12th, 2014
Table of Contents
Introduction.....................................................................................................................................3
Problem Description........................................................................................................................3
Materials and Procedure..................................................................................................................4
Results.............................................................................................................................................4
Discussion........................................................................................................................................6
Conclusion.......................................................................................................................................7
Appendix.........................................................................................................................................9Introduction
In this lab we used Xilinx ISE to create a simple processor. This processor needed to per-
form a variety of different functions, including not, add, jump, load accumulator and store and
clear accumulator processes, among others. We also needed to split up our code into four distinct
sections that dealt with the datapath, ALU, controller, and the actual processor module itself. In
order to do this, we wrote code in Verilog that would be able to define and implement these vari-
ous processes. Once the code was written, we used built-in features of ISE to simulate the output
of the processor and confirm that it indeed functioned in the desired manner. After completing
the design of the modules related to our simple processor, we concluded our work by instantiat-
ing a test bench and using it to run a simulation that showed the actual outputs of the code, which
verified that we had indeed satisfied the original tasks of the lab.
Problem Description
The primary task of this lab experiment was to create a simple processor through the im-
plementation and simulation of Verilog code. In order to accomplish this task, we needed to fo-
cus our work in four distinct sections: the datapath, the ALU, the control values, and the actual
processor module itself. Tables of information regarding control values and function definitions,
along with an overall data path diagram were given in order to aid us in this task. After writing
our code that accurately represented and defined these modules, we needed to verify our results
through the simulation and analysis of the overall ModelSim waveform. In essence, our task
could only be solved by creating, simulating, verifying, and analyzing Verilog code that acted as
a simple processor.
Materials and Procedure
Materials Used:
o XILINX ISE 14.2
Procedure:
1. Study the supplied architecture that uses a minimum CPI Von Newman approach.
2. Study the supplied controller flow diagram.
3. Design and code necessary modules.
4. Perform ModelSim simulation of simple processor code to verify project accuracy.
Results
Once we had all of our code working correctly, we used the ModelSim capabilities of
Xilinx to simulate the simple processor. The waveform of this simulation is shown below in Fig-
ures 1 through 3. The processor started operation at time 100ns and ended at 171ns.
Figure 1: Simulation Waveform
Figure 2: Simulation Waveform
Figure 3: Simulation Waveform
Looking at the PresentState variable, we could see how the processor would move through the
various states to perform the necessary operations. The state of the accumulator (y variable)
could also be observed to see how each instruction would change the result. For instance, at time
105ns the NOT instruction is processed and the contents of the accumulator changes from all ze-
ros to all ones.
Discussion
In this lab, we were tasked with building a simple processor. This processor required us
to define the behavior of 4 specific components: Datapath, Control, ALU, and Processor.
The datapath is used to define how the processor handles different instructions. Every in-
struction set architecture has a certain format to its instructions that is represented as a binary
string. The datapath must be able to recognize these binary strings and send them to different
portions of the hardware so that they can perform different operations. Some of these destina-
tions include the processor’s registers, the ALU, and memory, among others.
The control portion is used to set various control values that will be used by the datapath.
By reading the initial instruction, the control module sets all the necessary control bits, so that
the other modules can react accordingly to incoming instructions.
The ALU, which stands for Arithmetic Logic Unit, is used to perform arithmetic opera-
tions, such as addition and subtraction, on incoming values. It can be used to perform operations
such as “add,” which simply adds the values contained in two registers and puts it in a third reg-
ister. It can also be used to perform operations such as load word, which adds an immediate
value to the value of a register in order to locate a different register, and then load the value con-
tained in that register. Many other operations require the use of arithmetic operations as well,
which makes the ALU an integral component of the processor.
The processor module was simply a portion of code that tied all of the other components
together and made sure they functioned properly. With each portion working in tandem, we were
able to input a few select instructions and have to processor implement them accordingly.
The main difficulty with this lab was actually get started and figuring out how all the
modules would work together. We were able to design the ALU module fairly easily, but it took
some time before we understood how the datapath and control modules would fit together. Once
we had that understanding though, we realized how the control module would set all the control
values and that the datapath would use these control values to actually perform most of the de-
sired operations.
Conclusion
In this lab, we learned how to design very complex Verilog code, and how one can simu-
late and verify these results in the Xilinx software. We also learned how to design a simple pro-
cessor, and how to effectively code and implement such a program in computer architecture
projects. We also were able to ascertain information regarding various errors that could occur
during the coding process, and how to identify and correct them with the software and various
debugging methods.
Using this newly gained knowledge, we were able to successfully design, code, and ana-
lyze the various modules that we needed to successfully implement a simple processor. We were
also able to run one overarching ModelSim waveform generation that allowed us to see the entire
performance and accuracy of our program. We were also able to understand the function of the
many functions and variables utilized in our modules, but more importantly, we were able to
identify the ways in which we needed to alter these components to fit the necessary tasks for our
overall project.
Overall, the simple processor is an important program to be able to understand and create
in Xilinx. Although considered one of the most difficult tasks we will be assigned as undergradu-
ates, the knowledge and experiences gained from successfully completing such a task will prove
to be invaluable. This lab is also important in that it helps us understand the higher-level func-
tions of our complex code as well as the various applications that may be able to utilize it in or-
der to further our knowledge in this field and help us solve future electrical and computer engi-
neering projects.
Appendix: Code
ALU Module:`timescale 1ns / 1ps
module alu(y, MD, ALUc, z, c, c);
input [15:0] y; //input 1input [15:0] MD; //input 2input [2:0] ALUc; //opcode for ALU
output [15:0] z; //outputoutput c; //carry in/out
reg [15:0] z;reg c;
always @ (y or MD or ALUc) begincase (ALUc)
0: //NOTz = ~y;
1: //ADC{c, z} = y + MD;
//JPA doesn't use ALU3: //INCA
z = y + 1;4: //STA
z = 0'b000;5: //LDA
z = MD[15:0];endcase
endendmodule
Datapath Module: `timescale 1ns / 1ps
module Datapath(RD, clk, rstn, enableMD, enableAC, enablePC, enableIR, enableMA, select-muxMA, selectmuxPC, selectmuxA, ALUc, WD, A, RWn, PC, MA, y, IR, MD, c); input clk, rstn; input [15:0] RD; input enableAC, enableIR, enableMA, enableMD, enablePC, selectmuxA, selectmuxMA; input [2:0] ALUc; input [1:0] selectmuxPC; input RWn;
output [11:0] A; output [15:0] y; output [15:0] IR; output [11:0] MA; output [15:0] MD; output [11:0] PC; output [15:0] WD; output c;
reg [11:0] A; reg [15:0] IR; reg [11:0] PC; reg [15:0] y; //Accumulator reg [11:0] MA; reg [15:0] MD; reg [15:0] WD; reg c; //Corresponding to carry in state 15
wire enableAC, enableIR, enableMA, enableMD, enablePC, selectmuxA, selectmuxMA; wire [1:0] selectmuxPC; wire [2:0] ALUc; wire [15:0] z; //ALU store output
initial beginA = 0;y = 0;c = 0;PC = 0;
end
alu ALU(y, MD, ALUc, z, c, c);
always @ (posedge clk or MD or ALUc) begin
if (enableAC == 1)y = z; //Load y with ALU store output
end
always @ (posedge clk or negedge rstn) begincase (RWn)
0 : begin if (enableAC == 1)
WD = y;end1 : begin
if (enableMD == 1)MD = RD;
else if (enableIR == 1)IR = RD;
endendcase
case (selectmuxMA)0 : begin
if (enableMA == 1 && enableIR == 1)MA <= IR[11:0];
end1 : begin
if (enableMA == 1 && enableMD == 1)MA <= MD[11:0];
endendcase
case (selectmuxPC)0 : begin
if (enablePC == 1)PC <= PC + 1;
end1 : begin
if (enablePC == 1)PC <= IR[11:0];
end2 : begin
if (enablePC == 1)PC <= MD[11:0];
endendcase
end
always @ (posedge clk or MA or MD or PC) begin
case (selectmuxA)0 : begin
if (enablePC == 1)A = PC;
end1 : begin
if (enableMA == 1)A = MA;
endendcase
endendmodule
Controller Module: `timescale 1ns / 1psmodule Controller(IR, clk, rstn, y, enableMD, enableAC, enablePC, enableIR, enableMA, ALUc, RWn, selectmuxMA, selectmuxPC, selectmuxA, PresentState); input [3:0] IR; input clk; input rstn; input [15:0] y; //Accumulator
output enableAC, enableIR, enableMA, enableMD, enablePC, selectmuxA, select-muxMA, RWn; output [1:0] selectmuxPC; output [2:0] ALUc; output [4:0] PresentState;
reg c, enableAC, enableIR, enableMA, enableMD, enablePC, selectmuxA, select-muxMA;
reg [1:0] selectmuxPC;reg RWn;reg [4:0] PresentState, NextState;
parameter S0 = 5'd0, S1 = 5'd1, S2 = 5'd2, S3 = 5'd3, S4 = 5'd4, S5 = 5'd5, S6 = 5'd6, S7 = 5'd7, S8 = 5'd8, S9 = 5'd9, S10 = 5'd10, S11 = 5'd11, S12 = 5'd12, S13 = 5'd13, S14 = 5'd14, S15 = 5'd15, S16 = 5'd16;
assign ALUc = IR[3:1];
always @ (posedge clk or negedge rstn) begin if (rstn == 1'b0)
PresentState = S0; else
PresentState = NextState;end
always @(PresentState) beginenableAC = 0;enableMD = 0;enablePC = 0;enableIR = 0;enableMA = 0;selectmuxMA = 0;selectmuxPC = 2'b00;selectmuxA = 0;
RWn = 0; //Reset enables for every state
case(PresentState)S0: begin
// enableAC = 0;// enableMD = 0;
RWn = 1;enablePC = 1;enableIR = 1;
// enableMA = 0;// selectmuxMA = 0;
selectmuxPC = 2'b11;// selectmuxA = 0;// IR[15:0] <= M[PC];
NextState = S1; end
S1: begin// enableAC = 0;// enableMD = 0;
enablePC = 1;// enableIR = 0;// enableMA = 0;// selectmuxMA = 0;
selectmuxPC = 2'b00;// selectmuxA = 0;// PC[11:0] <= PC[11:0] + 1; //Handled by Datapath if (IR[3:1] == 3'b000) begin
NextState = S2; end
else if (IR[3:1] == 3'b011) begin NextState = S3;
end else if (IR[3:1] == 3'b010) begin
if (y > 0) beginif (IR[0] == 1'b1) begin
NextState = S4; endelse begin
NextState = S7; end
endelse begin
enablePC = 1;selectmuxPC = 2'b11;NextState = S0;
end end else
NextState = S8; end
S2: beginenableAC = 1;
// enableIR = 0;// enableMA = 0;// enableMD = 0;
enablePC = 1;selectmuxPC = 2'b11;
// y <= ~y; //ACNextState = S0;
end
S3: beginenableAC = 1;
// enableIR = 0;// enableMA = 0;// enableMD = 0;
enablePC = 1;selectmuxPC = 2'b11;
// y <= y+1; //ACNextState = S0;
end
S4: begin// enableAC = 0;
enableIR = 1;enableMA = 1;
// enableMD = 0;// enablePC = 0;
selectmuxA = 1;// MA[11:0] <= IR[11:0];
NextState = S5; end
S5: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxA = 1;
RWn = 1;// MD[15:0] <= M[MA];
NextState = S6;end
S6: begin// enableAC = 0;// enableIR = 0;// enableMA = 0;
enableMD = 1;enablePC = 1;selectmuxPC = 2'b10;
// PC[11:0] <= MD[15:0];NextState = S0;
end
S7: begin// enableAC = 0;
enableIR = 1;// enableMA = 0;// enableMD = 0;
enablePC = 1;selectmuxPC = 2'b01;
// PC[11:0] <= IR[11:0];NextState = S0;
end
S8: begin// enableAC = 0;
enableIR = 1;enableMA = 1;
// enableMD = 0;// enablePC = 0;
selectmuxMA = 0;// MA[11:0] <= IR[11:0];
if (IR[3:1] == 3'b100 && IR[0] == 1) NextState = S9; //STA & AM
else if (IR[3:1] == 3'b100 && IR[0] == 0) NextState = S11; //STA & ~AM
else NextState = S12;
end
S9: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxA = 1;RWn = 1;
// MD[15:0] <= M[MA];NextState = S10;
end
S10: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxMA = 1;
// MA[11:0] <= MD[15:0];NextState = S11;
end
S11: beginenableAC = 1;
// enableIR = 0;enableMA = 1;
// enableMD = 0;enablePC = 1;selectmuxPC = 2'b11;
// M[MA] <= y;// y <= 0'b000;
NextState = S0; end
S12: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxA = 1;RWn = 1;
// MD[15:0] <= M[MA];if (IR[0] == 1)
NextState = S13; //AMelse begin
if (IR[3:1] == 3'b001) NextState = S15; //ADC
else NextState = S16;
end end
S13: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxMA = 1;
// MA <= MD;NextState = S14;
end
S14: begin// enableAC = 0;// enableIR = 0;
enableMA = 1;enableMD = 1;
// enablePC = 0;selectmuxA = 1;RWn = 1;
// MD <= M[MA]; if (IR[3:1] == 3'b001)
NextState = S15; //ADC else
NextState = S16; end
S15: beginenableAC = 1;
// enableIR = 0;// enableMA = 0;
enableMD = 1;// enablePC = 0;// y <= y+MD[15:0]+C;
NextState = S0; end
S16: beginenableAC = 1;
// enableIR = 0;// enableMA = 0;
enableMD = 1;
enablePC = 1;selectmuxPC = 2'b11;
// y <= MD[15:0];NextState = S0;
endendcase
endendmodule
Processor Module:`timescale 1ns / 1ps
module processor(RD, clk, rstn, WD, A, IR, MD, y, PC, MA, PresentState, enableIR, enableMD, enableAC, enablePC, enableMA, selectmuxMA, selectmuxPC, selectmuxA, ALUc, c); input clk; input rstn; input [15:0] RD; output [11:0] A; output [15:0] IR; output [11:0] PC; output [11:0] MA; output [15:0] MD; output [15:0] WD; output [15:0] y; output enableAC; output enableIR; output enableMA; output enableMD; output enablePC; output [2:0] ALUc; output selectmuxA; output selectmuxMA; output [1:0] selectmuxPC; output [4:0] PresentState; output c; wire [15:0] IR; wire [11:0] PC; wire [11:0] MA; wire [15:0] MD; wire [11:0] A; wire [15:0] y; wire clk; wire rstn; wire [2:0] ALUc; wire enableAC; wire enableIR; wire enableMA; wire enableMD; wire enablePC; wire RWn; wire selectmuxA; wire selectmuxMA;
wire [1:0] selectmuxPC; Datapath datapath(RD, clk, rstn, enableMD, enableAC, enablePC, enableIR, enableMA,
selectmuxMA, selectmuxPC, selectmuxA, ALUc, WD, A, RWn, PC, MA, y, IR, MD, c); Controller controller(IR[15:12], clk, rstn, y, enableMD, enableAC, enablePC, enableIR,
enableMA, ALUc, RWn, selectmuxMA, selectmuxPC, selectmuxA, PresentState);
endmodule
Testbench: `timescale 1ns / 1ps
module Testbench; reg [15:0] RD; reg clk; reg rstn;
wire [15:0] IR; wire [11:0] PC; wire [11:0] MA; wire [15:0] MD; wire [15:0] WD; wire [11:0] A; wire [15:0] y; wire enableAC; wire enableIR; wire enableMA; wire enableMD; wire enablePC; wire [2:0] ALUc; wire c; wire selectmuxA; wire selectmuxMA; wire [1:0] selectmuxPC; wire [4:0] PresentState;
reg [15:0] M[4096:0]; //4096 is 2^12
// Instantiate the Unit Under Test (UUT) processor uut ( .RD(RD), .clk(clk), .rstn(rstn), .WD(WD), .A(A), .IR(IR), .MD(MD), .y(y), .PC(PC), .MA(MA), .PresentState(PresentState), .enableIR(enableIR), .enableMD(enableMD), .enableAC(enableAC),
.enablePC(enablePC), .enableMA(enableMA), .selectmuxMA(selectmuxMA), .selectmuxPC(selectmuxPC), .selectmuxA(selectmuxA), .ALUc(ALUc), .c(c) );
initial begin// Initialize Inputsclk = 0;rstn = 0;
//Memory to set every opcode and addressingM[0] <= 16'b0000000000000000;M[1] <= 16'b0010000000000100;M[2] <= 16'b0011000000001010;M[3] <= 16'b0110000000000000;M[4] <= 16'b0100000000000111;M[5] <= 16'b0101000000001011;M[6] <= 16'b1000000000000000;M[7] <= 16'b1001000000001011;M[8] <= 16'b1010000000000010;M[9] <= 16'b1011000000001010;M[10] <= 16'b0000000000001000;M[11] <= 16'b0000000000001010;
// Wait 100 ns for global reset to finish#100;
// Add stimulus hererstn = 1;RD <= M[A];
end
always @(clk) #1 clk <= ~clk; //Create clock
always @ (posedge clk or negedge rstn or A) beginRD <= M[A];
end
always @ (WD) beginif (WD == 0 && enableAC == 1)
M[A] <= WD; end
endmodule