Step 4 of Self-writing CPU (2) -- verify the implementation effect of the first instruction Ori

Source: Internet
Author: User

I will upload my new book "Write CPU by myself" (not published yet). Today is 12th articles. I try to write them every Thursday.

Change the title of "self-writing processor" to "self-writing CPU".


4.3 verify the implementation of openmips 4.3.1 instruction memory Rom

This section checks whether our openmips is implemented correctly, including: whether the pipeline is correct and whether the Ori command is implemented correctly. Before verification, you must first implement the instruction memory so that openmips can read the instruction from it.

The instruction memory module is read-only, and its interface is shown in 4-7. The left side is the input interface, and the right side is the output interface, which is easy to understand. The interface meanings are shown in Table 4-12.



The instruction memory Rom module is implemented in the file inst_rom.v. The Code is as follows. You can find the source file in the Code \ Chapter4 \ directory of the CD attached to this book.

Module inst_rom (input wirece, input wire ['instaddrbus] ADDR, output Reg ['instbus] insT); // defines an array with the size of instmemnum, the element width is instbusreg ['instbus] inst_mem [0: 'instmemnum-1]; // use the File inst_rom.data to initialize the command memory initial $ readmemh ("inst_rom.data", inst_mem ); // when the reset signal is invalid, the always @ (*) begin if (Ce = 'chipdisable) element in the instruction memory Rom is given based on the input address) begin inst <= 'zeroword; end else begin inst <= inst_mem [ADDR ['instmemnumlog2 +]; endendendmodule

The code is easy to understand and has the following instructions.

(1) the initial process statement is used when the command memory is initialized. The initial process statement is executed only once. It is usually used to describe the incentive vector in the simulation module or to assign an initial value to the variable. It is a process statement for simulation and cannot be supported by comprehensive tools. Therefore, if you want to integrate the openmips processor implemented in this chapter with a comprehensive tool, you need to modify the method for initializing command memory here.

(2) When initializing the instruction memory, the system function $ readmemh is used to read data from the inst_rom.data file to initialize inst_mem, and inst_mem is the previously defined array. Inst_rom.data is a text file that stores commands, and each row stores a 32-bit instruction (expressed in hexadecimal format ), the system function $ readmemh will enter the data in inst_rom.data into the inst_mem array in sequence.

(3) openmips adopts byte addressing, and each address in the instruction memory defined here is a 32bit character. Therefore, you must divide the instruction address given by openmips by 4 before using it. For example: to read the instruction at the address 0xc, it is actually corresponding to the ROM inst_mem [3], as shown in 4-8.


Divide by 4, that is, shift the command address to the right by two places. Therefore, the address given during reading is ADDR ['instmemnumlog2 +], where instmemnumlog2 is the actual address width of the command memory, for example: if inst_mem has 1024 elements, instmemnum equals 1024, and instmemnumlog2 equals 10, indicating that the actual address width is 10.

4.3.2 Implementation of the minimal-cost Support System

In order to verify, you need to establish a system-based system System. Openmips reads commands from the instruction memory and starts to execute the commands in openmips. The minimum part length is 4-9.


The smallest part of the system is openmips_min_systems, which is located in the openmips_min_sopc.v file. You can find this file in the Code \ Chapter4 \ directory of the CD attached to this book. The main content is as follows. In this example, the processor openmips and instruction memory Rom are used, and the two are connected as shown in Figure 4-9.

Module openmips_min_systems (inputwireclk, input wirerst); // connection command memory wire ['instaddrbus] inst_addr; wire ['instbus] inst; wire rom_ce; // example processor openmips openmips0 (. CLK (CLK ),. RST (RST ),. rom_addr_o (inst_addr ),. rom_data_ I (insT ),. rom_ce (rom_ce); // The rominst_rom inst_rom0 (. ce (rom_ce ),. ADDR (inst_addr ),. inst (insT); endmodule
4.3.3 compile the test program

We need to write a test program and store it to the instruction memory Rom. This way, when the minimum-level system file system established in the previous section starts running, our program will be retrieved from the Rom, it is sent to the openmips processor for execution. Currently, openmips only implements one Ori command, so the test program is very simple, as shown in the following figure. The inst_rom.s file under the CD Code \ Chapter4 \ testasm directory is attached to this book.

  ori $1,$0,0x1100        # $1 = $0 | 0x1100 = 0x1100  ori $2,$0,0x0020        # $2 = $0 | 0x0020 = 0x0020  ori $3,$0,0xff00        # $3 = $0 | 0xff00 = 0xff00  ori $4,$0,0xffff        # $4 = $0 | 0xffff = 0xffff

There are a total of four commands, all of which are Ori commands.

In the first command, 0 x 1st is scaled to zero and then the logic "or" operation is performed with register $0. The result is saved in register $1.

The 2nd commands perform a zero-scaling operation on 0x0020 and then perform a logical "or" Operation on the register $0. The result is saved in register $2.

3rd commands perform a zero-scaling 0xff00 operation with the register $0 and then perform a logical "or" operation. The result is saved in register $3.

4th commands perform the zero-scaling operation on 0xffff and then perform the logical "or" operation with the register $0. The result is saved in register $4.

The instruction annotation describes the execution result of the instruction. Next, we should use the compiler to compile our test program in the normal order. However, the installation and use of the GCC compiler, the preparation of makefile files, and other content still need to be explained in a lot of space, as readers and authors are eager to know whether openmips is correctly implemented, this section uses manual compilation to compile the test program. Section 4.4 will introduce the use of the GCC compiler.

For manual compilation, you only need to fill in the Ori Instruction format shown in Figure 4-1 according to the instruction content to obtain the corresponding binary characters. For example, for the instruction Ori $1, $1100 x, the corresponding binary word is 4-10.

Convert to a hexadecimal system, that is, 0x34011100. The other three commands can obtain the corresponding binary characters in the same way. According to the requirements of the $ readmemh function, one line of commands is placed, the isnt_rom.data file corresponding to the test program is as follows. You can find the file with the same name in the Code \ Chapter4 \ testasm directory of the CD attached to this book.

34011100340200203403ff003404ffff

4.3.4 create a test environment file

This section sets up the test environment file, which provides the clock signal and reset signal required for running the shortest system. The Code is as follows. The openmis_min_sopc_tb.v file under the CD Code \ Chapter4 \ directory is attached to this book.

// The unit of time is 1ns, and the precision is 1ps 'timescale 1ns/1 psmodule openmips_min_sopc_tb (); Reg clock_50; Reg RST; // The clock_50 signal is flipped once every 10ns, therefore, a period is 20 NS, corresponding to 50 MHz initial begin clock_50 = 1' B0; forever #10 clock_50 = ~ Clock_50; end // The reset signal is valid at the initial time. In the 195ns, the reset signal is invalid. The minimum value is that the system starts running the system. // after running 1000ns, the initial begin rst = 'rstenable is suspended; #195 rst = 'rstdisable; #1000 $ stop; end // Case-Based minimal e2openmips_min_e2openmips_min_sopc0 (. CLK (clock_50 ),. RST (RST); endmodule

4.3.5 use Modelsim to verify openmips implementation

Everything is ready for use. This section is the last step before verification-creating a Modelsim project for simulation. Refer to the introduction in Chapter 2nd to create a Modelsim project. The project name can be openmis_min_system, all the openmips source files, test history files, and command memory files created above (that is, all files under the CD Code \ Chapter4 directory attached to this book. V file) is added to the project, and then compiled.

Note: copy the inst_rom.data file created in the previous section to the project directory.

After the compilation is successful, switch the workspace to the library tab, open the library of work, select openmis_min_sopc_tb, right-click and choose simulate, as shown in Figure 4-11.


On the displayed waveform display page, add the signal to be observed to start simulation. Here, we select register $1-$4 as the observed object, as shown in 4-12. By observing the final value of register $1-$4, we can see that openmips correctly executes the test program, that is, the Ori command is correctly implemented.


Add more signals to be observed to understand the pipeline execution, as shown in Figure 4-13. In order to make the assembly line display more intuitive, the execution process of the first command in the assembly line is used as an example, and the signal changes caused by the execution of other commands are removed in the figure.

(1) In the first rising edge of the clock cycle after the reset, rom_ce_o changes to chipenable, which indicates that the instruction memory enables, starts to take the finger, and enters the fetch phase, obtain the first instruction 0x34011100 from the instruction memory and assign it to the input port if_inst of the IF/ID module. In the next clock cycle, the First Command enters the decoding phase.

(2) observe the decoding phase.

  • The instruction id_inst In the decoding phase is the first instruction 0x34011100.
  • Command address id_pc is 0x00000000
  • Decode the command in the ID module. The obtained command operation type alusel_o is 3'b001. The macro definition in the definition. h file shows that the macro exe_res_logic indicates logical operation.
  • The calculation subtype aluop_o is 8'b00100101. The macro definition in the definition. h file shows that the macro exe_or_op corresponds to the logical "or" operation.
  • The source operand 1 involved in the operation is 0x00000000, which is the value of the $0 register.
  • The decoded result shows that the source operand 2 involved in the operation is 0x00001100, Which is the value immediately after the number of zero extensions in the instruction.
  • The value of wreg_o obtained by decoding is 1, indicating that the destination register is to be written.
  • The destination register wd_o to be written through decoding is 5'b00001, which is exactly the $1 register.

(3) observe the execution phase.

  • After the specified operation, the wdata_o value is 0x00001100, which is the data to be written to the destination register.
  • The value of wreg_o in the transfer decoding stage. The value is 1, indicating that the destination register is to be written.
  • Transmit the value of wd_o In the decoding phase, which is 5'b00001, indicating that the destination register to be written is $1.

(4) observe the memory access phase

  • The value of wdata_o in the transfer stage, 0x00001100, indicating the data to be written to the destination register
  • Pass the value of wreg_o in the execution phase. The value is 1, indicating that the target register is to be written.
  • Pass the value of wd_o in the execution phase. The value is 5 'b00001, indicating that the destination register to be written is $1.

(5) observe the write-Back Stage

  • The value of wdata_o in the memory access phase is 0x00001100, indicating the data to be written to the destination register.
  • Obtain the value of wreg_o in the memory access phase. The value is 1, indicating that the target register is to be written.
  • The value of wd_o in the memory access phase is 5 'b00001, indicating that the destination register to be written is $1.

At the end of the write-back stage, the target register $1 will be written as required, so that the value of $1 is 0x00001100. Through the above observation, we can see that the original openmips five-level pipeline is implemented correctly. Next, we can add and implement more MIPS commands Based on this. However, before that, we must first learn how to use the GNU tool chain, in this example, there are only four commands that can be compiled manually. In the future, programs that are complicated and have more commands will become inefficient, therefore, you must use the GNU tool chain.


Not complete to be continued!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.