1 Department of Electrical and Computer Engineering Queen’s University ELEC-374 Digital Systems Engineering Laboratory Project Winter 2020 Designing a Simple RISC Computer: Phase 3 ----------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------- 1. Objectives The purpose of this project is to design, simulate, implement, and verify a simple RISC Computer (Mini SRC). So far, you have designed and functionally simulated the Datapath portion of the Mini SRC (except for nop and halt instructions that you will test in this phase). Phase 3 of this project consists of adding and testing the Control Unit in Mini SRC. You are to design the Control Unit in VHDL or Verilog. Testing will be done by Functional Simulation. 2. Preliminaries 2.1 Control Unit A block diagram of the Control Unit for Mini SRC is shown in Figure 1. The Control Unit is at the heart of the processor. It accepts as input those signals that are needed to operate the processor and provides as output all the control signals necessary to execute the instructions. The outputs from the Control Unit are the control signals that we have been using in the previous phases to generate control sequences for the instructions of the Mini SRC. Figure 1: Block diagram of the Control Unit 2 The Control Unit generates the control signals from four principal sources: (a) The op-code fields of the IR (b) Signals from the Datapath such as CON FF, and the condition code registers (if any) (c) Control step information such as signals T0, T1, … (d) External inputs such as Stop, Reset, Done (if memory is slow), and other signals such as interrupts (if any) The external Reset input should get the Mini SRC to an initial state, where all registers including PC in the Datapath are set to 0, the Run indicator is set to 1, and the processor starts at Step T0. As the clock continues to run, instructions should be fetched and executed one after the other until a halt instruction is encountered, at which point the control stepping process should be halted and the Run indicator is set to 0. Note that, the external Stop input signal works the same way as the halt instruction. During T0, T1, and T2, the control signals that are asserted to implement the “instruction fetch” sequence are independent of the bits in the Instruction Register. For instance, in Step T0, the control signals PCout, MARin, IncPC and Zin are set to 1. In Step T1, the control signals Zlowout, PCin, Read, and MDRin are set to 1. In Step T2, the control signals MDRout and IRin are set to 1. However, from Step T3 onward, until the current instruction is completed, the control signals that are asserted are a function of both Step Ti and the op-code bits in the IR register. In the following, you will see two different methods to design your Control Unit. There is a trade-off between the two methods. Method 1 is clearly the easier method, but it may generate more hardware. Of course, you are free to come up with your own design style, if you wish. Method 1: It is possible to write the VHDL/Verilog code without worrying about the combinational logic expressions for each control signal. Therefore, the code will come clean and the instructions will be executed in the most efficient manner. However, it may generate more hardware. The following sample VHDL and Verilog code are provided as a starting point for this method, which you may need to verify and revise for your Control Unit: -- this is the VHDL sample code for Method 1 for the Control Unit LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY control_unit IS -- here, you will define the inputs and outputs to your Control Unit PORT(Clock, Reset, Stop, …, CON_FF: IN STD_LOGIC; IR: IN STD_LOGIC_VECTOR(31 DOWNTO 0); Gra, Grb, Grc, Rin, …, Rout: OUT STD_LOGIC; Yin, Zin, PCout, IncPC, …, MARin: OUT STD_LOGIC; Read, Write, …, Clear: OUT STD_LOGIC; ADD, AND, …, SHR: OUT STD_LOGIC); END control_unit; ARCHITECTURE Behavior of control_unit IS TYPE State IS (Reset_state, fetch0, fetch1, fetch2, add3, add4, add5, …); SIGNAL Present_state: State; BEGIN PROCESS (Clock, Reset) -- finite state machine BEGIN IF (Reset = ‘1’) THEN -- reset the processor 3 Present_state <= Reset_state; ELSIF (rising_edge(Clock)) THEN -- if clock rising-edge CASE Present_state IS WHEN Reset_state => Present_state <= fetch0; WHEN fetch0 => Present_state <= fetch1; WHEN fetch1 => Present_state <= fetch2; WHEN fetch2 => -- instruction decoding based on the opcode to set the next state CASE IR(31 DOWNTO 27) IS WHEN “00011” => -- this is the add instruction Present_state <= add3; ⁞ WHEN OTHERS => END CASE; WHEN add3 => Present_state <= add4; WHEN add4 => Present_state <= add5; ⁞ WHEN OTHERS => END CASE; END IF; END PROCESS; PROCESS (Present_state) -- do the job for each state BEGIN CASE Present_state IS -- assert the required signals in each state WHEN Reset_state => Gra <= ‘0’; -- initialize the signals Grb <= ‘0’; Grc <= ‘0’; Yin <= ‘0’; ⁞ WHEN fetch0 => PCout <= ‘1’; -- see if you need to de-assert these signals MARin <= ‘1’; IncPC <= ‘1’; Zin <= ‘1’; WHEN add3 => Grb <= ‘1’; Rout <= ‘1’; Yin <= ‘1’; ⁞ WHEN nop => WHEN OTHERS => END CASE; END PROCESS; END Behavior; ----------------------------------------------------- // this is the Verilog sample code for Method 1 for the Control Unit 4 `timescale 1ns/10ps module control_unit ( output reg Gra, Grb, Grc, Rin, …, Rout, // here, you will define the inputs and outputs to your Control Unit Yin, Zin, PCout, IncPC, …, MARin, Read, Write, …, Clear, ADD, AND, …, SHR, input [31:0] IR, input Clock, Reset, Stop, …, Con_FF); parameter Reset_state = 4’b0000, fetch0 = 4’b0001, fetch1 = 4’b0010, fetch2 = 4’b0011, add3 = 4’b0100, add4 = 4’b0101, add5 = 4’b0110, …; reg [3:0] Present_state = Reset_state; // adjust the bit pattern based on the number of states always @(posedge Clock, posedge Reset) // finite state machine; if clock or reset rising-edge begin if (Reset == 1’b1) Present_state = Reset_state; else case (Present_state) Reset_state : Present_state = fetch0; fetch0 : Present_state = fetch1; fetch1 : Present_state = fetch2; fetch2 : begin case (IR[31:27]) // inst. decoding based on the opcode to set the next state 5’b00011 : Present_state = add3; // this is the add instruction ⁞ endcase end add3 : Present_state = add4; add4 : Present_state = add5; ⁞ endcase end always @(Present_state) // do the job for each state begin case (Present_state) // assert the required signals in each state Reset_state: begin Gra <= 0; Grb <= 0; Grc <= 0; Yin <= 0; // initialize the signals ⁞ end fetch0: begin PCout <= 1; // see if you need to de-assert these signals MARin <= 1; IncPC <= 1; Zin <= 0; end add3: begin Grb <= 1; Rout <= 1; Yin <= 0; end ⁞ endcase end endmodule 5 Method 2: In this approach, you will need to derive all control signal setting conditions for all instructions. For this, you must examine all of the control sequences of the machine. The logic for each control signal is generated by going through the control sequences looking for every occurrence of that control signal and writing the Boolean equation for the signal. For example, the Zlowout signal occurs at T1 in all instructions, at T5 in and, or, add, sub, mul, div, shr, shl, ror, rol, ld, and ldi instructions, and in some T states for other instructions. Therefore, Zlowout = T1 + T5 . (AND + OR + ADD + SUB + MUL + DIV + SHR + SHL + ROR + ROL + …) + … The problem with this approach is that the logic for each control signal may change with the addition of new instructions, therefore this approach is provided here merely for the sake of completeness. You are advised to use Method 1, especially if you intend to extend the scope of the project by adding new instructions, etc. The following sample VHDL and Verilog code are provided as a starting point for Method 2, which you may need to verify and revise for your Control Unit: -- this is the VHDL sample code for Method 2 for the Control Unit LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY control_unit IS -- Here, you will define the inputs and outputs to your Control Unit PORT(Clock, Reset, Stop, …, CON_FF: IN STD_LOGIC; IR: IN STD_LOGIC_VECTOR(31 DOWNTO 0); Gra, Grb, Grc, Rin, …, Rout: OUT STD_LOGIC; Yin, Zin, PCout, IncPC, Zlowout, …, MARin: OUT STD_LOGIC; Read, Write, …, Clear: OUT STD_LOGIC; ADD, AND, …, SHR: OUT STD_LOGIC); END control_unit; ARCHITECTURE Behavior of control_unit IS SIGNAL T0, T1, T2, T3, T4, T5, …, : STD_LOGIC; SIGNAL ADD_s, SUB_s, AND_s, OR_s, …, : STD_LOGIC; TYPE State IS (Reset_state, S0, S1, …, ); SIGNAL Present_state: State; BEGIN PROCESS (Clock, Reset, …) -- finite state machine BEGIN IF (Reset = ‘1’) THEN -- reset the processor Present_state <= Reset_state; ELSIF (rising_edge(Clock)) THEN -- if clock rising-edge T0 <= ‘0’; T1 <= ‘0’; T2 <= ‘0’; T3 <= ‘0’; T4 <= ‘0’; T5 <= ‘0’; … CASE Present_state IS WHEN Reset_state => Present_state <= S0; T0 <= ‘1’; WHEN S0 => Present_state <= S1; T1 <= ‘1’; ⁞ WHEN OTHERS => 6 END CASE; END IF; END PROCESS; PROCESS (IR) BEGIN ADD_s <= ‘0’; AND_s <= ‘0’; … CASE IR(31 DOWNTO 27) IS -- inst. decoding based on the opcode WHEN “00011” => ADD_s <= ‘1’; -- this is the add instruction WHEN “01001” => AND_s <= ‘1’; -- this is the and instruction ⁞ WHEN OTHERS => END CASE; END PROCESS; PROCESS (Clock, T0, T1, …) BEGIN ADD <= ADD_s AND T4; -- control signal assignment Zlowout <= T1 OR (T5 AND (AND_s OR OR_s OR ADD_s OR SUB_s OR …)) OR …; ⁞ END PROCESS; END Behavior; ----------------------------------------------------- // this is the Verilog sample code for Method 2 for the Control Unit `timescale 1ns/10ps module control_unit ( output reg Gra, Grb, Grc, Rin, …, Rout, // here, you will define the inputs and outputs to your Control Unit Yin, Zin, PCout, IncPC, Zlowout, …, MARin, Read, Write, …, Clear, ADD, AND, …, SHR, input [31:0] IR, input Clock, Reset, Stop, …, Con_FF); parameter Reset_state = 4’b0000, S0 = 4’b0001, S1 = 4’b0010, …; reg [3:0] Present_state = Reset_state; // adjust the bit pattern based on the number of states reg T0, T1, T2, T3, T4, T5, ..., ; reg ADD_s, SUB_s, AND_s, OR_s, ..., : always @(posedge Clock, posedge Reset, …) // finite state machine; if clock or reset rising-edge begin if (Reset == 1’b1) Present_state = Reset_state; // reset the processor else begin T0 <= 0; T1 <= 0; T2 <= 0; T3 <= 0; T4 <= 0; T5 <= 0; case (Present_state) Reset_state: begin Present_state = S0; T0 <= 1; end 7 S0: begin Present_state = S1; T1 <= 1; end ⁞ endcase end end always @(IR) begin ADD_s <= 0; AND_s <= 0; … case (IR[31:27]) // inst. decoding based on the opcode 5’b00011: ADD_s <= 1; // this is the add instruction 5’b01001: AND_s <= 1; // this is the and instruction ⁞ endcase end always @(Clock, T0, T1, …) begin ADD <= ADD_s && T4; // control signal assignment Zlowout <= T1 || (T5 && (AND_s || OR_s || ADD_s || SUB_s || …)) || …; ⁞ end endmodule 3. Procedure 3.1) Use one of the above Methods (or come up with your own design style) and write your VHDL/Verilog code to implement the Control Unit. Add the Control Unit to your Datapath. 3.2) Run a functional simulation of the following program on Mini SRC and put the results in your report. Note that this program is provided just for the sake of testing the control unit and the instructions in Mini SRC, except for brnz/brzr Branch and Input/Output instructions that will be included in the test code for Phase 4. This year, due to remote delivery, Phase 4 will in not be a part of the course as we do not have physical access to the DE0 boards. Encode your program in the memory with the starting address zero. Initialize the memory locations $75 and $58 with the 32-bit values $56 and $34, respectively. Minimum outputs are IR, PC, MDR, MAR, R0 – R15, HI, and LO. Add any other signals you would like to observe to convince yourself that your design works fine. ORG 0 ldi R3, $87 ; R3 = $87 ldi R3, 1(R3) ; R3 = $88 ld R2, $75 ; R2 = ($75) = $56 8 ldi R2, -2(R2) ; R2 = $54 ld R1, 4(R2) ; R1 = ($58) = $34 ldi R0, 1 ; R0 = 1 ldi R3, $73 ; R3 = $73 brmi R3, 3 ; continue with the next instruction (will not branch) ldi R3, 5(R3) ; R3 = $78 ld R7, -3(R3) ; R7 = ($78 - 3) = $56 nop brpl R7, 2 ; continue with the instruction at “target” (will branch) ldi R4, 6(R1) ; this instruction will not execute ldi R3, 2(R4) ; this instruction will not execute target: add R3, R2, R3 ; R3 = $CC addi R7, R7, 3 ; R7 = $59 neg R7, R7 ; R7 = $FFFFFFA7 not R7, R7 ; R7 = $58 andi R7, R7, $0F ; R7 = 8 ori R7, R1, 3 ; R7 = $37 shr R2, R3, R0 ; R2 = $66 st $58, R2 ; ($58) = $66 new value in memory with address $58 ror R1, R1, R0 ; R1 = $1A rol R2, R2, R0 ; R2 = $CC or R2, R3, R0 ; R2 = $CD and R1, R2, R1 ; R1 = $8 st $67(R1), R2 ; ($75) = $CD new value in memory with address $75 sub R3, R2, R3 ; R3 = 1 shl R1, R2, R0 ; R1 = $19A ldi R4, 5 ; R4 = 5 ldi R5, $1D ; R5 = $1D mul R5, R4 ; HI = 0; LO = $91 mfhi R7 ; R7 = 0 mflo R6 ; R6 = $91 div R5, R4 ; HI = 4, LO = 5 ldi R10, 0(R4) ; R10 = 5 setting up argument registers ldi R11, 2(R5) ; R11 = $1F R8, R9, R10, and R11 ldi R12, 0(R6) ; R12 = $91 ldi R13, 0(R7) ; R13 = 0 jal R12 ; address of subroutine subA in R12 - return address in R14 halt ; upon return, the program halts subA: ORG $91 ; procedure subA add R9, R10, R12 ; R8 and R9 are return value registers sub R8, R11, R13 ; R9 = $96, R8 = $1F sub R9, R9, R8 ; R13 = $77 jr R14 ; return from procedure 9 4. Report The phase 3 report (one per group) consists of: - Printouts of your VHDL/Verilog code, and schematic (if any) - Functional simulation run of the program - Printouts of the contents of memory before and after the program run
欢迎咨询51作业君