OpenCores
URL https://opencores.org/ocsvn/steelcore/steelcore/trunk

Subversion Repositories steelcore

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 12 to Rev 11
    Reverse comparison

Rev 12 → Rev 11

/steelcore/docs/images/dfetch_wave.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
steelcore/docs/images/dfetch_wave.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/dwrite_wave.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/dwrite_wave.png =================================================================== --- steelcore/docs/images/dwrite_wave.png (nonexistent) +++ steelcore/docs/images/dwrite_wave.png (revision 11)
steelcore/docs/images/dwrite_wave.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/ifetch_wave.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/ifetch_wave.png =================================================================== --- steelcore/docs/images/ifetch_wave.png (nonexistent) +++ steelcore/docs/images/ifetch_wave.png (revision 11)
steelcore/docs/images/ifetch_wave.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/irq_wave.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/irq_wave.png =================================================================== --- steelcore/docs/images/irq_wave.png (nonexistent) +++ steelcore/docs/images/irq_wave.png (revision 11)
steelcore/docs/images/irq_wave.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/riscv-steel-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/riscv-steel-32.png =================================================================== --- steelcore/docs/images/riscv-steel-32.png (nonexistent) +++ steelcore/docs/images/riscv-steel-32.png (revision 11)
steelcore/docs/images/riscv-steel-32.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/steel-fsm.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/steel-fsm.png =================================================================== --- steelcore/docs/images/steel-fsm.png (nonexistent) +++ steelcore/docs/images/steel-fsm.png (revision 11)
steelcore/docs/images/steel-fsm.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/steel-interface.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/steel-interface.png =================================================================== --- steelcore/docs/images/steel-interface.png (nonexistent) +++ steelcore/docs/images/steel-interface.png (revision 11)
steelcore/docs/images/steel-interface.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/steel-logo.svg =================================================================== --- steelcore/docs/images/steel-logo.svg (nonexistent) +++ steelcore/docs/images/steel-logo.svg (revision 11) @@ -0,0 +1,3 @@ + + +
steel
ste...
CORE
CORE
Viewer does not support full SVG 1.1
\ No newline at end of file Index: steelcore/docs/images/steel-pipe.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/steel-pipe.png =================================================================== --- steelcore/docs/images/steel-pipe.png (nonexistent) +++ steelcore/docs/images/steel-pipe.png (revision 11)
steelcore/docs/images/steel-pipe.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/steel-soc.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/steel-soc.png =================================================================== --- steelcore/docs/images/steel-soc.png (nonexistent) +++ steelcore/docs/images/steel-soc.png (revision 11)
steelcore/docs/images/steel-soc.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/images/timeup_wave.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: steelcore/docs/images/timeup_wave.png =================================================================== --- steelcore/docs/images/timeup_wave.png (nonexistent) +++ steelcore/docs/images/timeup_wave.png (revision 11)
steelcore/docs/images/timeup_wave.png Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: steelcore/docs/config.md =================================================================== --- steelcore/docs/config.md (nonexistent) +++ steelcore/docs/config.md (revision 11) @@ -0,0 +1,26 @@ +# Configuration + +Steel configuration parameters can be modified by editing the `globals.vh` file (located inside the `rtl` directory). The following subsections describe the parameters that can be changed. + +## Boot address + +The `BOOT_ADDRESS` parameter sets the memory position of the first instruction the core will fetch after reset. It can be changed to any 32-bit value. + +## CSRs reset values + +The reset value of several control and status registers (CSRs) can be modified. The table below shows these CSRs and the accepted values. + +| **Parameter name** | **Description** | +| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| *MCYCLE_RESET* | Value of the `mcycle` CSR after reset. It can be changed to any 32-bit value. | +| *MCYCLEH_RESET* | Value of the `mcycleh` CSR after reset. It can be changed to any 32-bit value. | +| *TIME_RESET* | Value of the `time` CSR after reset. It can be changed to any 32-bit value. | +| *TIMEH_RESET* | Value of the `timeh` CSR after reset. It can be changed to any 32-bit value. | +| *MINSTRET_RESET* | Value of the `minstret` CSR after reset. It can be changed to any 32-bit value. | +| *MINSTRETH_RESET* | Value of the `minstreth` CSR after reset. It can be changed to any 32-bit value. | +| *MTVEC_BASE_RESET* | Value of the `base` field of `mtvec` CSR after reset. The value is used in the trap handler address calculation. It can be changed to any 30-bit value. | +| *MTVEC_MODE_RESET* | Value of the `mode` field of `mtvec` CSR after reset. It defines the interrupt mode and can be changed to the value 00 (direct mode) or 01 (vectored mode). | +| *MSCRATCH_RESET* | Value of the `mscratch` CSR after reset. It can be changed to any 32-bit value. | +| *MEPC_RESET* | Value of the `mepc` CSR after reset. It can be changed to any 32-bit address aligned on a four byte boundary (the last two bits must be set to zero). | +| *MCOUNTINHIBIT_CY_RESET* | Enables or inhibits cycle counting (1 inhibits, 0 enables). | +| *MCOUNTINHIBIT_IR_RESET* | Enables or inhibits instructions retired counting (1 inhibits, 0 enables). | Index: steelcore/docs/details.md =================================================================== --- steelcore/docs/details.md (nonexistent) +++ steelcore/docs/details.md (revision 11) @@ -0,0 +1,279 @@ +# Implementation Details + +This section contains information on implementation details. It is intended for those who want to know more about how Steel works. + +## Implemented CSRs + +The control and status registers implemented in Steel are shown in table 1, below. The required M-mode registers not shown in the table return the hardwired value predicted by the specifications when read. + +

+Table 1. Implemented CSRs +

+ +| **CSR** | **Name** | **Address** | +| :----------------- | :----------------------------------- | ----------: | +| cycle | *Cycle Counter* | 0xC00 | +| time | *System Timer* | 0xC01 | +| instret | *Instructions Retired* | 0xC02 | +| mstatus | *Machine Status* | 0x300 | +| misa | *Machine ISA* | 0x301 | +| mie | *Machine Interrupt Enable* | 0x304 | +| mtvec | *Machine Trap Vector* | 0x305 | +| mscratch | *Machine Scratch* | 0x340 | +| mepc | *Machine Exception Program Counter* | 0x341 | +| mcause | *Machine Cause* | 0x342 | +| mtval | *Machine Trap Value* | 0x343 | +| mip | *Machine Interrupt Pending* | 0x344 | +| mcycle | *Machine Cycle Counter* | 0xB00 | +| minstret | *Machine Instructions Retired* | 0xB01 | +| mcountinhibit | *Machine Counter Inhibit* | 0x320 | + +## Modules + +### Control Unit + +The Control Unit (**control_unit.v**) decodes the instruction and generates the signals that control the memory, the Load Unit, the Store Unit, the ALU, the two register files (Integer and CSR), the Immediate Generator and the Writeback Multiplexer. The description of its input and output signals are shown in table 2, below. + +

+Table 2. Branch Unit input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :------------------------------------ | :--------- | :------------- | :-------------------------------------------------------------------------------------------------------------------- | +| **OPCODE\_7\_TO\_2** | 5 bits | Input | Connected to the instruction *opcode* field. | +| **FUNCT7\_5** | 1 bit | Input | Connected to the instruction *funct7* field. | +| **FUNCT3** | 3 bits | Input | Connected to the instruction *funct3* field. | +| **IADDER\_OUT\_1\_TO\_0** | 2 bits | Input | Used to verify the alignment of loads and stores. | +| **TRAP\_TAKEN** | 1 bit | Input | When set high indicates that a trap will be taken in the next clock cycle. Connected to the Machine Control module. | +| **ALU\_OPCODE** | 4 bits | Output | Selects the operation to be performed by the ALU. | +| **MEM\_WR\_REQ** | 1 bit | Output | When set high indicates a request to write to memory. | +| **LOAD\_SIZE** | 2 bits | Output | Indicates the word size of load instruction. | +| **LOAD\_UNSIGNED** | 1 bit | Output | Indicates the type of load instruction (signed or unsigned). | +| **ALU\_SRC** | 1 bit | Output | Selects the ALU 2nd operand. | +| **IADDER\_SRC** | 1 bit | Output | Selects the Immediate Adder 2nd operand. | +| **CSR\_WR\_EN** | 1 bit | Output | Controls the WR\_EN input of CSR Register File. | +| **RF\_WR\_EN** | 1 | Output | Controls the WR\_EN input of Integer Register File. | +| **WB\_MUX\_SEL** | 3 | Output | Selects the data to be written in the Integer Register File. | +| **IMM\_TYPE** | 3 | Output | Selects the immediate based on the type of the instruction. | +| **CSR\_OP** | 3 | Output | Selects the operation to be performed by the CSR Register File (read/write, set or clear). | +| **ILLEGAL\_INSTR** | 1 bit | Output | When set high indicates that an invalid or not implemented instruction was fetched from memory. | +| **MISALIGNED\_LOAD** | 1 bit | Output | When set high indicates an attempt to read data in disagreement with the memory alignment rules. | +| **MISALIGNED\_STORE** | 1 bit | Output | When set high indicates an attempt to write data to memory in disagreement with the memory alignment rules. | + +### ALU + +The ALU (**alu.v**) applies ten distinct logical and arithmetic operations in parallel to two 32-bit operands, outputting the result selected by `OPCODE`. The ALU input/output signals and the opcodes are shown in tables 3 and 4, below. + +The opcode values were assigned to facilitate instruction translation. The most significant bit of `OPCODE` matches with the second most significant bit in the instruction **funct7** field. The remaining three bits match with the instruction **funct3** field. + +

+Table 3. ALU input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :------------------------- | :--------- | :------------- | :----------------------------------------------------------------------------------------------------------------- | +| **OP\_1** | 32 bits | Input | Operation first operand. | +| **OP\_2** | 32 bits | Input | Operation second operand. | +| **OPCODE** | 4 bits | Input | Operation code. This signal is driven by *funct7* and *funct3* instruction fields. | +| **RESULT** | 32 bits | Output | Result of the requested operation. | + +

+Table 4. ALU opcodes +

+ +| **Opcode** | **Operation** | **Binary value** | +| :------------------ | :------------------------ | :---------------- | +| **ALU\_ADD** | Addition | 4'b0000 | +| **ALU\_SUB** | Subtraction | 4'b1000 | +| **ALU\_SLT** | Set on less than | 4'b0010 | +| **ALU\_SLTU** | Set on less than unsigned | 4'b0011 | +| **ALU\_AND** | Bitwise logical AND | 4'b0111 | +| **ALU\_OR** | Bitwise logical OR | 4'b0110 | +| **ALU\_XOR** | Bitwise logical XOR | 4'b0100 | +| **ALU\_SLL** | Logical left shift | 4'b0001 | +| **ALU\_SRL** | Logical right shift | 4'b0101 | +| **ALU\_SRA** | Arithmetic right shift | 4'b1101 | + +### Integer Register File + +The Integer Register File (**integer\_file.v**) has 32 general-purpose registers and supports read and write operations. Reads are requested in the pipeline stage 2 and provide data from one or two registers. Writes are requested in the pipeline stage 3 and put the data coming from the Writeback Multiplexer into the selected register. If stage 3 requests to write to a register being read by stage 2, the data to be written is immediately forwarded to stage 2. Each operation is driven by a distinct set of signals, shown in the tables 5 and 6, below. + +

+Table 5. Integer Register File signals for read +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :--------------------- | :--------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **RS\_1\_ADDR** | 5 bits | Input | *Register source 1 address*. The data is placed at `RS_1` immediately after an address change. | +| **RS\_2\_ADDR** | 5 bits | Input | *Register source 2 address*. The data is placed at `RS_2` immediately after an address change. | +| **RS\_1** | 32 bits | Output | Data read (source 1). | +| **RS\_2** | 32 bits | Output | Data read (source 2). | + +

+Table 6. Integer Register File signals for write +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :--------------------- | :--------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **RD\_ADDR** | 5 bits | Input | *Destination register address*. | +| **RD** | 32 bits | Input | Data to be written in the destination register. | +| **WR\_EN** | 1 bit | Input | *Write enable*. When set high, the data placed on RD is written in the destination register at the next clock rising edge. | + +### Branch Unit + +The Branch Unit (**branch\_unit.v**) decides if a branch instruction must be taken or not. It receives two operands from the Integer Register File and, based on the value of *opcode* and *funct3* instruction fields, decides the branch. Jump instructions are interpreted as branches that must always be taken. Internally, the unit realizes just two comparisions, deriving other four from them. Table 7 (below) shows the module input and output signals. + +

+Table 7. Branch Unit input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :-------------------- | :--------- | :------------- | :------------------------------------------------------- | +| **OPCODE\_7\_TO\_2** | 5 bits | Input | Connected to the *opcode* instruction field. | +| **FUNCT3** | 3 bits | Input | Connected to the *funct3* instruction field. | +| **RS1** | 32 bits | Input | Connected to the Integer Register File 1st operand source. | +| **RS2** | 32 bits | Input | Connected to the Integer Register File 2nd operand source. | +| **BRANCH\_TAKEN** | 1 bit | Output | High if the branch must be taken, low otherwise. | + +### Load Unit + +The Load Unit (**load\_unit.v**) reads `DATA_IN` input signal and forms a 32-bit value based on the load instruction type (encoded in the *funct3* field). The formed value (placed on `OUTPUT`) can then be written in the Integer Register File. The module input and output signals are shown in table 8. The value of OUTPUT is formed as shown in table 9. + +

+Table 8. Load Unit input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :--------------------------- | :--------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **LOAD\_SIZE** | 2 bits | Input | Connected to the two least significant bits of the *funct3* instruction field. | +| **LOAD\_UNSIGNED** | 1 bit | Input | Connected to the most significant bit of the *funct3* instruction field. | +| **DATA\_IN** | 32 bits | Input | 32-bit word read from memory. | +| **IADDER\_OUT\_1\_TO\_0** | 2 bits | Input | Indicates the byte/halfword position in `DATA_IN`. Used only with load byte/halfword instructions. | +| **OUTPUT** | 32 bits | Output | 32-bit value to be written in the Integer Register File. | + +

+Table 9. Load Unit output generation +

+ +| **LOAD\_SIZE** | **Effect on OUTPUT** | +| :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **2'b00** | The byte in the position indicated by `IADDER_OUT_1_TO_0` is placed on the least significant byte of `OUTPUT`. The upper 24 bits are filled according to the `LOAD_UNSIGNED` signal. | +| **2'b01** | The halfword in the position indicated by `IADDER_OUT_1_TO_0` is placed on the least significant halfword of `OUTPUT`. The upper 16 bits are filled according to the `LOAD_UNSIGNED` signal. | +| **2'b10** | All bits of `DATA_IN` are placed on OUTPUT. | +| **2'b11** | All bits of `DATA_IN` are placed on OUTPUT. | +| **LOAD\_UNSIGNED** | **Effect on OUTPUT** | +| **1'b0** | The remaining bits of `OUTPUT` are filled with the sign bit. | +| **1'b1** | The remaining bits of `OUTPUT` are filled with zeros. | + +### Store Unit + +The Store Unit (**store\_unit.v**) drives the signals that interface with memory. It places the data to be written (which can be a byte, halfword or word) in the right position in `DATA_OUT` and sets the value of `WR_MASK` in an appropriate way. Table 10 (below) shows the unit input and output signals. + +

+Table 10. Store Unit input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :-------------------- | :--------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **FUNCT3** | 3 bits | Input | Connected to the *funct3* instruction field. Indicates the data size (byte, halfword or word). | +| **IADDER\_OUT** | 32 bits | Input | Contains the address (possibly unaligned) where the data must be written. | +| **RS2** | 32 bits | Input | Connected to Integer Register File source 2. Contains the data to be written (possibly in the wrong position). | +| **MEM\_WR\_REQ** | 1 bit | Input | Control signal generated by the Control Unit. When set high indicates a request to write to memory. | +| **DATA\_OUT** | 32 bits | Output | Contains the data to be written in the right position. | +| **D\_ADDR** | 32 bits | Output | Contains the address (aligned) where the data must be written. | +| **WR\_MASK** | 4 bits | Output | A bitmask that indicates which bytes of `DATA_OUT` must be written. | +| **WR\_REQ** | 1 bit | Output | When set high indicates a request to write to memory. | + +### Immediate Generator + +The Immediate Generator (**imm\_generator.v**) rearranges the immediate bits contained in the instruction and, if necessary, sign-extends it to form a 32-bit value. The unit is controlled by the `IMM_TYPE` signal, generated by the Control Unit. Table 11 shows the unit input and output signals. + +

+Table 11. Immediate Generator input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :------------------ | :--------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| **INSTR** | 25 bits | Input | Connected to the instruction bits (32 to 7). | +| **IMM\_TYPE** | 2 bits | Input | Control signal generated by the Control Unit that indicates the type of immediate that must be generated. | +| **IMM** | 32 bits | Output | 32-bit generated immediate. | + +### CSR Register File + +The CSR Register File (**csr_file.v**) has the control and status registers required for the implementation of M-mode. Read/write, set and clear operations can be applied to the registers. Table 12 shows the unit input and output signals, except those used for communication with the Machine Control module, which are shown in table 13. + +

+Table 12. CSR Register File input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :----------------------------- | :--------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | +| **WR\_EN** | 1 bit | Input | *Write enable*. When set high, updates the CSR addressed by `CSR_ADDR` at the next clock rising edge according to the operation selected by `CSR_OP`. | +| **CSR\_ADDR** | 12 bits | Input | Address of the CSR to read/write/modify. | +| **CSR\_OP** | 3 bits | Input | Control signal generated by the Control Unit. Selects the operation to be performed (read/write, set, clear or no operation). | +| **CSR\_UIMM** | 5 bits | Input | *Unsigned immediate*. Connected to the five least significant bits from the Immediate Generator output. | +| **CSR\_DATA\_IN** | 32 bits | Input | In write operations, contains the data to be written. In set or clear operations, contains a bit mask. | +| **PC** | 32 bits | Input | *Program counter* value. Used to update the `mepc` CSR. | +| **E\_IRQ** | 1 bit | Input | *External interrupt request*. Used to update the MEIP bit of `mip` CSR. | +| **T\_IRQ** | 1 bit | Input | *Timer interrupt request*. Used to update the MTIP bit of `mip` CSR. | +| **S\_IRQ** | 1 bit | Input | *Software interrupt request*. Used to update the MSIP bit of `mip` CSR. | +| **REAL\_TIME** | 64 bits | Input | Current value of the real time counter. Used to update the `time` and `timeh` CSRs. | +| **CSR\_DATA\_OUT** | 32 bits | Output | Contains the data read from the CSR addressed by `CSR_ADDR`. | +| **EPC\_OUT** | 32 bits | Output | Current value of the `mepc` CSR. | +| **TRAP\_ADDRESS** | 32 bits | Output | Address of the trap handler first instruction. | + +

+Table 13. CSR Register File and Machine Control module interface signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :----------------------------------------------------------------------------------------------------------------- | :--------- | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **I\_OR\_E** | 1 bit | Input | *Interrupt or exception*. When set high indicates an interrupt, otherwise indicates an exception. Used to update the most significant bit of `mcause` register. | +| **CAUSE\_IN** | 4 bits | Input | Contains the exception code. Used to update the `mcause` register. | +| **SET\_CAUSE** | 1 bit | Input | When set high updates the `mcause` register with the values of `I_OR_E` and `CAUSE_IN`. | +| **SET\_EPC** | 1 bit | Input | When set high, updates the `mepc` register with the value of PC. | +| **INSTRET\_INC** | 1 bit | Input | When set high enables the instructions retired counting. | +| **MIE\_CLEAR** | 1 bit | Input | When set high sets the MIE bit of `mstatus` to zero (which globally disables interrupts). The old value of MIE is saved in the `mstatus` MPIE field. | +| **MIE\_SET** | 1 bit | Input | When set high sets the MPIE bit of `mstatus` to one. The old value of MPIE is saved in the `mstatus` MIE field. | +| **MIE** | 1 bit | Output | Current value of MIE bit of `mstatus` CSR. | +| **MEIE\_OUT** | 1 bit | Output | Current value of MEIE bit of `mie` CSR. | +| **MTIE\_OUT** | 1 bit | Output | Current value of MTIE bit of `mie` CSR. | +| **MSIE\_OUT** | 1 bit | Output | Current value of MSIE bit of `mie` CSR. | +| **MEIP\_OUT** | 1 bit | Output | Current value of MEIP bit of `mip` CSR. | +| **MTIP\_OUT** | 1 bit | Output | Current value of MTIP bit of `mip` CSR. | +| **MSIP\_OUT** | 1 bit | Output | Current value of MSIP bit of `mip` CSR. | + +### Machine Control + +The Machine Control module (**machine_control.v**) implements the M-mode, controlling the the program counter generation and updating several CSRs. It has a special communication interface with the CSR Register File, already shown in table 13 (above). Its input and output signals are shown in table 14 (below). + +Internally, the module implements the finite state machine shown in figure 1 (below). + +

+Table 14. Machine Control input/output signals +

+ +| **Signal name** | **Width** | **Direction** | **Description** | +| :----------------------------------- | :--------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **ILLEGAL\_INSTR** | 1 bit | Input | *Illegal instruction*. When set high indicates that an invalid or not implemented instruction was fetched from memory. | +| **MISALIGNED\_INSTR** | 1 bit | Input | *Misaligned instruction*. When set high indicates an attempt to fetch an instruction which address is in disagreement with the memory alignment rules. | +| **MISALIGNED\_LOAD** | 1 bit | Input | *Misaligned load*. When set high indicates an attempt to read data in disagreement with the memory alignment rules. | +| **MISALIGNED\_STORE** | 1 bit | Input | *Misaligned store*. When set high indicates an attempt to write data to memory in disagreement with the memory alignment rules. | +| **OPCODE\_7\_TO\_2** | 5 bits | Input | Value of the *opcode* instruction field. | +| **FUNCT3** | 3 bits | Input | Value of the *funct3* instruction field. | +| **FUNCT7** | 7 bits | Input | Value of the *funct7* instruction field. | +| **RS1\_ADDR** | 5 bits | Input | Value of the *rs1* instruction field. | +| **RS2\_ADDR** | 5 bits | Input | Value of the *rs2* instruction field. | +| **RD\_ADDR** | 5 bits | Input | Value of the *rd* instruction field. | +| **E\_IRQ** | 1 bit | Input | *External interrupt request*. | +| **T\_IRQ** | 1 bit | Input | *Timer interrupt request*. | +| **S\_IRQ** | 1 bit | Input | *Software interrupt request*. | +| **PC\_SRC** | 2 bit | Output | Selects the program counter source. | +| **FLUSH** | 1 bit | Output | Flushes the pipeline when set. | +| **TRAP\_TAKEN** | 1 bit | Output | When set high indicates that a trap will be taken in the next clock cycle. | + +

+Figure 1. Machine Control finite state machine +

+ +![Machine Control FSM](images/steel-fsm.png) Index: steelcore/docs/extra.css =================================================================== --- steelcore/docs/extra.css (nonexistent) +++ steelcore/docs/extra.css (revision 11) @@ -0,0 +1,7 @@ +th, td { + padding: 10px; +} + +table { + margin-bottom: 20px; +} Index: steelcore/docs/getting.md =================================================================== --- steelcore/docs/getting.md (nonexistent) +++ steelcore/docs/getting.md (revision 11) @@ -0,0 +1,48 @@ +# Getting Started + +## What you need to know first + +Steel must be connected to a word-addressed memory with read/write latency of 1 clock cycle. Block RAM IPs (e. g. *Xilinx Block Memory Generator* or *Intel RAM Megafunction*) can be easily configured to meet these requirements. The interfaces to fetch instructions and to read/write data were designed to facilitate the integration with FPGA Block RAMs. + +If you do not need hardware timers, you must connect the `REAL_TIME` bus to a hardwired value. Otherwise, you must connect it to a real-time counter. The `E_IRQ`, `T_IRQ`, and `S_IRQ` signals (used to request for interrupts) can be connected to a single device or to an interrupt controller that manages interrupts from multiple devices. If interrupts are not needed, these signals must be connected to zero. + +## Using Steel in your project + +To use Steel in your project you must import all files from the `rtl` directory to it. Then instantiate Steel using the following template: + +```verilog +steel_top core( + .CLK( ), + .RESET( ), + .REAL_TIME( ), + .I_ADDR( ), + .INSTR( ), + .D_ADDR( ), + .DATA_OUT( ), + .WR_REQ( ), + .WR_MASK( ), + .DATA_IN( ), + .E_IRQ( ), + .T_IRQ( ), + .S_IRQ( ) +); +``` + +Read the section [Input and Output Signals](steelio.md) for more information on the input/output signals above. + +## Writing software for Steel + +You can write, compile and assemble C/C++ software for Steel with [RISC-V GNU Toolchain](https://github.com/riscv/riscv-gnu-toolchain). Follow the instructions in the [README.md](https://github.com/riscv/riscv-gnu-toolchain/blob/master/README.md) file for installing the Newlib cross-compiler. **Don't forget** to add the options `--with-arch=rv32i` and `--with-abi=ilp32` when configuring the installation: + +``` +./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32 +make +``` + +To run the software you wrote you must initialize the memory with it. If you use a Block RAM IP as memory, you can initialize it by converting the ELF file generated by the compiler to a memory initialization file (HEX, MIF, COE, or other formats, depending on the FPGA you use). + +## Example system + +The figure below shows an example of how Steel can be used as processing unit in embedded systems projects. The same architecture can be used to build other systems. The example is composed of a dual-port Block RAM, a memory mapped GPIO unit, a bus arbiter, an interrupt controller and a real-time counter. In this system, the address space is divided into two ranges, one assigned to memory and the other to the GPIO unit. The bus arbiter is used to multiplex the data interface signals according to the address the core wants to access. + +![Steel SoC example](images/steel-soc.png) Index: steelcore/docs/index.md =================================================================== --- steelcore/docs/index.md (nonexistent) +++ steelcore/docs/index.md (revision 11) @@ -0,0 +1,31 @@ +# Overview + +## About Steel Core + +Steel is a 3-stage single-issue in-order RISC-V microprocessor core designed to be simple and easy to use. It is intended for use in FPGAs as the processing unit in embedded systems projects. + +**Key features:** + +* Easy to use +* Targeted for use in FPGAs +* Implements the RV32I base instruction set + Zicsr extension +* M-mode privilege level support +* Hardware described in Verilog +* 3 pipeline stages +* Single-issue +* Fully documented + +## Licensing + +Steel is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). The license text is reproduced in the `LICENCE.md` file. Read it carefully and make sure you understand its terms before using Steel in your own projects. + +## Specifications version + +Steel aims to be compliant with the following RISC-V specifications: + +* Version **20191213** of RISC-V Unprivileged ISA +* Version **20190608-Priv-MSU-Ratified** of RISC-V Privileged Architecture + +## Online repository + +Steel files and documentation are available at GitHub ([github.com/rafaelcalcada/steel-core](https://github.com/rafaelcalcada/steel-core)). Index: steelcore/docs/overview.md =================================================================== --- steelcore/docs/overview.md (nonexistent) +++ steelcore/docs/overview.md (revision 11) @@ -0,0 +1,31 @@ +# Overview + +## About Steel Core + +Steel is a 3-stage single-issue in-order RISC-V microprocessor core designed to be simple and easy to use. It is intended for use in FPGAs as the processing unit in embedded systems projects. + +**Key features:** + +* Easy to use +* Targeted for use in FPGAs +* Implements the RV32I base instruction set + Zicsr extension +* M-mode privilege level support +* Hardware described in Verilog +* 3 pipeline stages +* Single-issue +* Fully documented + +## Licensing + +Steel is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). The license text is reproduced in the `LICENCE.md` file. Read it carefully and make sure you understand its terms before using Steel in your own projects. + +## Specifications version + +Steel aims to be compliant with the following RISC-V specifications: + +* Version **20191213** of RISC-V Unprivileged ISA +* Version **20190608-Priv-MSU-Ratified** of RISC-V Privileged Architecture + +## Online repository + +Steel files and documentation are available at GitHub ([github.com/rafaelcalcada/steel-core](https://github.com/rafaelcalcada/steel-core)). Index: steelcore/docs/steelio.md =================================================================== --- steelcore/docs/steelio.md (nonexistent) +++ steelcore/docs/steelio.md (revision 11) @@ -0,0 +1,50 @@ +# Input and Output Signals + +The figure below shows Steel input and output signals (except CLK and RESET). The following sections explain their functions in detail. + +The interfaces to fetch instructions and to read/write data can be connected to any type of memory, but were designed to facilitate integration with Block RAMs in FPGAs. + +![Steel IO](images/steel-interface.png) + +## Interrupt controller interface + +The interrupt controller interface has three signals used to request external, timer and software interrupts, shown in the table below. The interrupt request process is explained in the sections [Exceptions and Interrupts](traps.md) and [Timing Diagrams / Interrupt Request](timing.md#interrupt-request). + +| **Signal** | **Width** | **Direction** | **Description** | +| :----------------- | :--------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| *E_IRQ* | 1 bit | Input | When set high indicates an external interrupt request. | +| *T_IRQ* | 1 bit | Input | When set high indicates a timer interrupt request. | +| *S_IRQ* | 1 bit | Input | When set high indicates a software interrupt request. | + +## Instruction fetch interface + +The instruction fetch interface has two signals used in the instruction fetch process, shown in the table below. The process of fetching instructions is explained in the section [Timing Diagrams / Instruction Fetch](timing.md#instruction-fetch). + +| **Signal** | **Width** | **Direction** | **Description** | +| :---------------- | :--------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| *INSTR* | 32 bits | Input | Contains the instruction fetched from memory. | +| *I_ADDR* | 32 bits | Output | Contains the address of the instruction the core wants to fetch from memory. | + +## Data read/write interface + +The data read/write interface has five signals used in the process of reading/writing data from/to memory. The signals are shown in the table below. The process of fetching data from memory is explained in the section [Timing Diagrams / Data fetch](timing.md#data-fetch). The process of writing data is explained in the section [Timing Diagrams / Data writing](timing.md#data-writing). + +| **Signal** | **Width** | **Direction** | **Description** | +| :---------------- | :--------- | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| *DATA_IN* | 32 bits | Input | Contains the data fetched from memory. | +| *D_ADDR* | 32 bits | Output | In a write operation, contains the address of the memory position where the data will be stored. In a read operation, contains the address of the memory position where the data to be fetched is. The address is always aligned on a four byte boundary (the last two bits are always zero). | +| *DATA_OUT* | 32 bits | Output | Contains the data to be stored in memory. Used only with write operations. | +| *WR_REQ* | 1 bit | Output | When high, indicates a request to write data. Used only with write operations. | +| *WR_MASK* | 4 bits | Output | Contains a mask of four *byte-write enable* bits. A bit high indicates that the corresponding byte must be written. Used only with write operations. | + +## Real-time counter interface + +The real time counter interface has just one signal used to update the `time` CSR, shown in the table below. The process of updating the `time` register is explained in the section [Timing Diagrams / time CSR update](timing.md#time-csr-update). + +| **Signal** | **Width** | **Direction** | **Description** | +| :---------- | :--------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| *REAL_TIME* | 64 bits | Input | Contains the current value read from a real time counter. | + +## CLK and RESET signals + +The core also has the `CLK` and `RESET` input signals, which are not shown in the figure above. The `CLK` signal must be connected to a clock source. The `RESET` signal is active high and resets the core asynchronously. Index: steelcore/docs/timing.md =================================================================== --- steelcore/docs/timing.md (nonexistent) +++ steelcore/docs/timing.md (revision 11) @@ -0,0 +1,46 @@ +# Timing Diagrams + +## Instruction fetch + +To fetch an instruction, the core places the instruction address on the `I_ADDR` bus. The memory must place the instruction on the `INSTR` bus at the next clock rising edge. The figure below shows the timing diagram of this process. In the figure, **mem[addrX]** denotes the instruction stored at the memory position **addrX**. + +![Instruction fetch timing diagram](images/ifetch_wave.png) + +## Data fetch + +To fetch data from memory, the core puts the data address on the `D_ADDR` bus. The memory must place the data on the `DATA_IN` bus at the next clock rising edge. The figure below shows the timing diagram of this process. In the figure, **mem[addrX]** denotes the data stored at the memory position **addrX**. + +![Data fetch timing diagram](images/dfetch_wave.png) + +## Data writing + +To write data to memory, the core drives `D_ADDR`, `DATA_OUT`, `WR_REQ` and `WR_MASK` signals as follows: + +* `D_ADDR` receives the address of the memory position where the data must be written; +* `DATA_OUT` receives the data to be written; +* `WR_REQ` is set high; +* `WR_MASK` receives a byte-write enable mask that indicates which bytes of `DATA_OUT` must be written. + +The memory must perform the write operation at the next clock rising edge. The core can request to write bytes, halfwords and words. + +The figure below shows the process of writing data to memory. `DATA_IN` is not used in the process and appears only to show the memory contents after writing. The figure shows five clock cycles, in which the core requests to write in the second, third and fourth cycles. In the second clock cycle, the core requests to write the word **0x12345678** at the address **addr2**. In the third, requests to write the halfword **0xABCD** at the upper half of **addr2**, and in the fourth requests to write the byte **0xEF** at the second least significant byte of **addr2**. The content of **addr2** after each of these operations appears on the `DATA_IN` bus and are highlighted in blue. + +![Data writing timing diagram](images/dwrite_wave.png) + +## Interrupt request + +An external device (or an interrupt controller managing several devices) can request interrupts by setting high the appropriate IRQ signal, which is `E_IRQ` for external interrupts, `T_IRQ` for timer interrupts and `S_IRQ` for software interrupts. The IRQ signal of the requested interrupt must be set high for one clock cycle and set low for the next. + +The figure below shows the timing diagram of the interrupt request process. Since the process is the same for all types of interrupt, **X_IRQ** is used to denote `E_IRQ`, `T_IRQ` or `S_IRQ`. **TRAP_ADDR** denotes the address of the trap handler first instruction. + +

+ +

+ +## *time* CSR update + +When connected to a real-time counter, the core updates the `time` CSR with the value placed on `REAL_TIME` at each clock rising edge, as shown in the figure below. **timeX** denotes arbitrary time values. + +

+ +

Index: steelcore/docs/traps.md =================================================================== --- steelcore/docs/traps.md (nonexistent) +++ steelcore/docs/traps.md (revision 11) @@ -0,0 +1,39 @@ +# Exceptions and Interrupts + +## Supported exceptions and interrupts + +Steel supports the exceptions and interrupts shown in the table below. They are listed in descending priority order (the highest priority is at the top of the table). If two or more exceptions/interrupts occur at the same time, the one with the highest priority is taken. + +Exceptions always cause a trap to be taken. An interrupt will cause a trap only if enabled. Each type of interrupt has an interrupt-enable bit in the `mie` register. Interrupts are globally enable/disabled by setting the MIE bit of `mstatus` register. + +| **Exception / Interrupt** | `mcause` **interrupt bit** | `mcause` **exception code** | +| :--------------------------------------- | ----------------: | ------------------: | +| Machine external interrupt | 1 | 11 | +| Machine software interrupt | 1 | 3 | +| Machine timer interrupt | 1 | 7 | +| Illegal instruction exception | 0 | 2 | +| Instruction address-misaligned exception | 0 | 0 | +| Environment call from M-mode exception | 0 | 11 | +| Environment break exception | 0 | 3 | +| Store address-misaligned exception | 0 | 6 | +| Load address-misaligned exception | 0 | 4 | + +## Trap handling in Steel + +Exceptions and interrupts are handled by a trap handler routine stored in memory (your software must provide one). The address of the trap handler first instruction is configured using the `mtvec` register. Steel supports both direct and vectorized interrupt modes. More information on interrupt modes and configuration of the `mtvec` register can be found in [RISC-V specifications](https://riscv.org/specifications/). + +When a trap is taken, the core proceeds as follows: + +* the address of the interrupted instruction (or the instruction that encountered the exception) is saved in the `mepc` register; +* the value of the `mtval` register is set to zero; +* the value of the `mstatus` MIE bit is saved in the MPIE field and then set to zero; +* the program counter is set to the address of the trap handler first instruction. + +The **mret** instruction is used to return from traps. When executed, the core proceeds as follows: + +* the value of the `mstatus` MPIE bit is saved in the MIE field and then set to one; +* the program counter is set to the value of `mepc` register. + +## Nested interrupts capability + +The core globally disables new interrupts when takes into a trap. The trap handler can re-enable interrupts by setting the `mstatus` MIE bit to one, thus enabling nested interrupts. To return from nested traps, the trap handler must stack and manage the values of the `mepc` register in memory. Index: steelcore/docs/uarch.md =================================================================== --- steelcore/docs/uarch.md (nonexistent) +++ steelcore/docs/uarch.md (revision 11) @@ -0,0 +1,20 @@ +# Microarchitecture + +Steel has 3 pipeline stages, a single execution thread and issues only one instruction per clock cycle. Therefore, all instructions are executed in program order. + +Fig. 1 (below) shows the Steel microarchitecture in register-transfer level (RTL). Circles and trapezoids represent combinational logic units. Rectangles represent sequential logic units. Implementation details can be found in the section [Implementation Details](details.md). + +![Steel uArch](images/riscv-steel-32.png) +

+**Fig. 1:** Steel Core microarchitecture +

+ +Fig. 2 (below) shows the tasks performed by each pipeline stage. In the first stage, the core generates the program counter and fetches the instruction from memory. In the second, the instruction is decoded and the control signals for all units are generated. Branches, jumps and stores are executed in advance in this stage, which also generates the immediates and fetches the data from memory for load instructions. The last stage executes all other instructions and writes back the results in the register file. + +

+ +
+
+Fig. 2: Steel Core pipeline overview +

+ Index: steelcore/trunk/bench/tb_alu.v =================================================================== --- steelcore/trunk/bench/tb_alu.v (nonexistent) +++ steelcore/trunk/bench/tb_alu.v (revision 11) @@ -0,0 +1,361 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 03.04.2020 18:35:35 +// Module Name: tb_alu +// Project Name: Steel Core +// Description: RISC-V Steel Core 32-bit ALU testbench +// +// Dependencies: alu.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_alu(); + + reg [31:0] OP_1; + reg [31:0] OP_2; + reg [3:0] OPCODE; + wire [31:0] RESULT; + + alu dut( + + .OP_1( OP_1), + .OP_2( OP_2), + .OPCODE( OPCODE), + .RESULT( RESULT) + + ); + + reg [31:0] expected_result; + integer i; + + initial + begin + + $display("Testing ALU..."); + + $display("Executing extreme values test for ADD and SUB operations..."); + + OP_1 = 32'h00000001; // decimal = 1 + OP_2 = 32'h7FFFFFFF; // the biggest positive decimal + OPCODE = `ALU_ADD; + expected_result = 32'h80000000; // the lowest negative decimal + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'h80000000; // the lowest negative decimal + OP_2 = 32'h00000001; // decimal = 1 + OPCODE = `ALU_SUB; + expected_result = 32'h7FFFFFFF; // the biggest positive decimal + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'h00000000; // decimal = 0 + OP_2 = 32'h00000001; // decimal = 1 + OPCODE = `ALU_SUB; + expected_result = 32'hFFFFFFFF; // decimal = -1 + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'hFFFFFFFF; // decimal = -1 + OP_2 = 32'h00000001; // decimal = 1 + OPCODE = `ALU_ADD; + expected_result = 32'h00000000; // decimal = 0 + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'h00000001; // decimal = 1 + OP_2 = 32'hFFFFFFFF; // decimal = -1 + OPCODE = `ALU_ADD; + expected_result = 32'h00000000; // decimal = 0 + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'h00000001; // decimal = 1 + OP_2 = 32'hFFFFFFFF; // decimal = -1 + OPCODE = `ALU_SUB; + expected_result = 32'h00000002; // decimal = 2 + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + OP_1 = 32'hFFFFFFFF; // decimal = -1 + OP_2 = 32'h00000001; // decimal = 1 + OPCODE = `ALU_SUB; + expected_result = 32'hFFFFFFFE; // decimal = -2 + #10; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Test successful."); + $display("Testing 10000 pseudorandom values for all operations..."); + + $display("Testing ADD operation..."); + OPCODE = `ALU_ADD; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 + OP_2; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("ADD operation successfully tested."); + + $display("Testing SUB operation..."); + OPCODE = `ALU_SUB; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 - OP_2; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SUB operation successfully tested."); + + $display("Testing SLTU operation..."); + OPCODE = `ALU_SLTU; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = {31'b0, OP_1 < OP_2}; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SLTU operation successfully tested."); + + $display("Testing SLT operation..."); + OPCODE = `ALU_SLT; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = {31'b0, $signed(OP_1) < $signed(OP_2)}; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SLT operation successfully tested."); + + $display("Testing AND operation..."); + OPCODE = `ALU_AND; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 & OP_2; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("AND operation successfully tested."); + + $display("Testing OR operation..."); + OPCODE = `ALU_OR; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 | OP_2; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("OR operation successfully tested."); + + $display("Testing XOR operation..."); + OPCODE = `ALU_XOR; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 ^ OP_2; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("XOR operation successfully tested."); + + $display("Testing SLL operation..."); + OPCODE = `ALU_SLL; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 << OP_2[4:0]; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SLL operation successfully tested."); + + $display("Testing SRL operation..."); + OPCODE = `ALU_SRL; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = OP_1 >> OP_2[4:0]; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SRL operation successfully tested."); + + $display("Testing SRA operation..."); + OPCODE = `ALU_SRA; + for(i = 0; i < 10000; i=i+1) + begin + + OP_1 = $random; + OP_2 = $random; + #10; + expected_result = $signed(OP_1) >>> OP_2[4:0]; + if (RESULT != expected_result) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + $display("SRA operation successfully tested."); + + $display("All ALU operations successfully tested for pseudorandom values."); + + $display("ALU successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_branch_unit.v =================================================================== --- steelcore/trunk/bench/tb_branch_unit.v (nonexistent) +++ steelcore/trunk/bench/tb_branch_unit.v (revision 11) @@ -0,0 +1,520 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 18:45:28 +// Module Name: tb_branch_unit +// Project Name: Steel Core +// Description: RISC-V Steel Core Branch Decision Unit testbench +// +// Dependencies: branch_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_branch_unit(); + + reg [6:2] OPCODE_6_TO_2; + reg [31:0] RS1; + reg [31:0] RS2; + reg [2:0] FUNCT3; + wire BRANCH_TAKEN; + + integer i = 0; + reg signed [31:0] rs1s; + reg signed [31:0] rs2s; + + branch_unit dut( + .OPCODE_6_TO_2(OPCODE_6_TO_2), + .RS1(RS1), + .RS2(RS2), + .FUNCT3(FUNCT3), + .BRANCH_TAKEN(BRANCH_TAKEN) + ); + + initial + begin + + $display("Testing Branch Unit..."); + + $display("Testing branch comparator unit for BEQ."); + + FUNCT3 = 3'b000; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + + #10; + + if(RS1 == RS2 && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(RS1 != RS2 && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = $random; + RS2 = RS1; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + $display("Branch comparator works fine for BEQ."); + + $display("Testing branch comparator unit for BNE."); + + FUNCT3 = 3'b001; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + + #10; + + if(RS1 != RS2 && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(RS1 == RS2 && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = $random; + RS2 = RS1; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + $display("Branch comparator works fine for BNE."); + + $display("Testing branch comparator unit for BLT."); + + FUNCT3 = 3'b100; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + rs1s = RS1; + rs2s = RS2; + #10; + + if(rs1s < rs2s && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(rs1s >= rs2s && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b11111111_11111111_11111111_11111100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b00000000_00000000_00000000_00001000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + $display("Branch comparator works fine for BLT."); + + $display("Testing branch comparator unit for BGE."); + + FUNCT3 = 3'b101; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + rs1s = RS1; + rs2s = RS2; + #10; + + if(rs1s >= rs2s && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(rs1s < rs2s && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b11111111_11111111_11111111_11111100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b00000000_00000000_00000000_00001000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + $display("Branch comparator works fine for BGE."); + + $display("Testing branch comparator unit for BLTU."); + + FUNCT3 = 3'b110; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + + #10; + + if(RS1 < RS2 && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(RS1 >= RS2 && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b11111111_11111111_11111111_11111100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b00000000_00000000_00000000_00001000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + $display("Branch comparator works fine for BLTU."); + + $display("Testing branch comparator unit for BGEU."); + + FUNCT3 = 3'b111; + OPCODE_6_TO_2 = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + RS1 = $random; + RS2 = $random; + + #10; + + if(RS1 >= RS2 && BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + if(RS1 < RS2 && BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b11111111_11111111_11111111_11111100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b00000000_00000000_00000000_00001000; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b11111111_11111111_11111111_11111000; + RS2 = 32'b00000000_00000000_00000000_00001100; + #10; + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + RS1 = 32'b00000000_00000000_00000000_00001100; + RS2 = 32'b11111111_11111111_11111111_11111000; + #10; + if(BRANCH_TAKEN != 1'b0) + begin + $display("FAIL. Expected BRANCH_TAKEN = 0."); + $finish; + end + + $display("Branch comparator works fine for BGEU."); + + $display("Testing branch comparator unit for JAL."); + + FUNCT3 = 3'bxxx; + OPCODE_6_TO_2 = `OPCODE_JAL; + + #10; + + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + $display("Branch comparator works fine for JAL."); + + $display("Testing branch comparator unit for JALR."); + + FUNCT3 = 3'bxxx; + OPCODE_6_TO_2 = `OPCODE_JALR; + + #10; + + if(BRANCH_TAKEN != 1'b1) + begin + $display("FAIL. Expected BRANCH_TAKEN = 1."); + $finish; + end + + $display("Branch comparator works fine for JALR."); + + $display("Branch Unit successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_control_unit.v =================================================================== --- steelcore/trunk/bench/tb_control_unit.v (nonexistent) +++ steelcore/trunk/bench/tb_control_unit.v (revision 11) @@ -0,0 +1,1475 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 03.04.2020 18:35:35 +// Module Name: tb_control_unit +// Project Name: Steel Core +// Description: RISC-V Steel Core Control Unit testbench +// +// Dependencies: control_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + + +module tb_control_unit(); + + reg [6:0] OPCODE; + reg FUNCT7_5; + reg [2:0] FUNCT3; + reg [1:0] IADDER_OUT_1_TO_0; + reg TRAP_TAKEN; + + wire [3:0] ALU_OPCODE; + wire MEM_WR_REQ; + wire [1:0] LOAD_SIZE; + wire LOAD_UNSIGNED; + wire ALU_SRC; + wire IADDER_SRC; + wire CSR_WR_EN; + wire RF_WR_EN; + wire [2:0] WB_MUX_SEL; + wire [2:0] IMM_TYPE; + wire [2:0] CSR_OP; + wire ILLEGAL_INSTR; + wire MISALIGNED_LOAD; + wire MISALIGNED_STORE; + + control_unit dut( + + .OPCODE(OPCODE), + .FUNCT7_5(FUNCT7_5), + .FUNCT3(FUNCT3), + .IADDER_OUT_1_TO_0(IADDER_OUT_1_TO_0), + .TRAP_TAKEN(TRAP_TAKEN), + .ALU_OPCODE(ALU_OPCODE), + .MEM_WR_REQ(MEM_WR_REQ), + .LOAD_SIZE(LOAD_SIZE), + .LOAD_UNSIGNED(LOAD_UNSIGNED), + .ALU_SRC(ALU_SRC), + .IADDER_SRC(IADDER_SRC), + .CSR_WR_EN(CSR_WR_EN), + .RF_WR_EN(RF_WR_EN), + .WB_MUX_SEL(WB_MUX_SEL), + .IMM_TYPE(IMM_TYPE), + .CSR_OP(CSR_OP), + .ILLEGAL_INSTR(ILLEGAL_INSTR), + .MISALIGNED_LOAD(MISALIGNED_LOAD), + .MISALIGNED_STORE(MISALIGNED_STORE) + + ); + + reg [4:0] opcode_6_to_2; + reg [6:0] funct7; + + initial + begin + + $display("Testing Control Unit..."); + + $display("Testing OP opcode control signals..."); + + $display("Testing signals common to all instructions..."); + + opcode_6_to_2 = `OPCODE_OP; + OPCODE = {opcode_6_to_2, 2'b11}; + IADDER_OUT_1_TO_0 = 2'b00; + TRAP_TAKEN = 1'b0; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ALU_SRC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WB_MUX_SEL != `WB_ALU) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("OP control signals common to all instructions successfully tested."); + + $display("Testing ALU_OPCODE signal generation for OP opcode..."); + + funct7 = `FUNCT7_ADD; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_ADD; + #10; + if(ALU_OPCODE != `ALU_ADD) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for ADD... OK."); + + funct7 = `FUNCT7_SUB; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SUB; + #10; + if(ALU_OPCODE != `ALU_SUB) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SUB... OK."); + + funct7 = `FUNCT7_SLT; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SLT; + #10; + if(ALU_OPCODE != `ALU_SLT) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLT... OK."); + + funct7 = `FUNCT7_SLTU; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SLTU; + #10; + if(ALU_OPCODE != `ALU_SLTU) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLTU... OK."); + + funct7 = `FUNCT7_AND; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_AND; + #10; + if(ALU_OPCODE != `ALU_AND) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for AND... OK."); + + funct7 = `FUNCT7_OR; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_OR; + #10; + if(ALU_OPCODE != `ALU_OR) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for OR... OK."); + + funct7 = `FUNCT7_XOR; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_XOR; + #10; + if(ALU_OPCODE != `ALU_XOR) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for XOR... OK."); + + funct7 = `FUNCT7_SLL; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SLL; + #10; + if(ALU_OPCODE != `ALU_SLL) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLL... OK."); + + funct7 = `FUNCT7_SRL; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SRL; + #10; + if(ALU_OPCODE != `ALU_SRL) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SRL... OK."); + + funct7 = `FUNCT7_SRA; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SRA; + #10; + if(ALU_OPCODE != `ALU_SRA) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SRA... OK."); + + $display("ALU_OPCODE signal generation for OP opcode successfully tested."); + + $display("OP control signals successfully tested."); + + $display("Testing OP-IMM opcode control signals..."); + + $display("Testing signals common to all instructions..."); + + opcode_6_to_2 = `OPCODE_OP_IMM; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ALU_SRC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WB_MUX_SEL != `WB_ALU) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `I_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("OP-IMM control signals common to all instructions successfully tested."); + + $display("Testing ALU_OPCODE signal generation for OP-IMM opcode..."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_ADD; + #10; + if(ALU_OPCODE != `ALU_ADD) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_ADD; + #10; + if(ALU_OPCODE != `ALU_ADD) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for ADDI... OK."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_SLT; + #10; + if(ALU_OPCODE != `ALU_SLT) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_SLT; + #10; + if(ALU_OPCODE != `ALU_SLT) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLTI... OK."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_SLTU; + #10; + if(ALU_OPCODE != `ALU_SLTU) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_SLTU; + #10; + if(ALU_OPCODE != `ALU_SLTU) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLTIU... OK."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_AND; + #10; + if(ALU_OPCODE != `ALU_AND) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_AND; + #10; + if(ALU_OPCODE != `ALU_AND) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for ANDI... OK."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_OR; + #10; + if(ALU_OPCODE != `ALU_OR) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_OR; + #10; + if(ALU_OPCODE != `ALU_OR) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for ORI... OK."); + + FUNCT7_5 = 1'b0; + FUNCT3 = `FUNCT3_XOR; + #10; + if(ALU_OPCODE != `ALU_XOR) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT7_5 = 1'b1; + FUNCT3 = `FUNCT3_XOR; + #10; + if(ALU_OPCODE != `ALU_XOR) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for XORI... OK."); + + funct7 = `FUNCT7_SLL; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SLL; + #10; + if(ALU_OPCODE != `ALU_SLL) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SLLI... OK."); + + funct7 = `FUNCT7_SRL; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SRL; + #10; + if(ALU_OPCODE != `ALU_SRL) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SRLI... OK."); + + funct7 = `FUNCT7_SRA; + FUNCT7_5 = funct7[5]; + FUNCT3 = `FUNCT3_SRA; + #10; + if(ALU_OPCODE != `ALU_SRA) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ALU_OPCODE for SRAI... OK."); + + $display("ALU_OPCODE signal generation for OP-IMM opcode successfully tested."); + + $display("OP-IMM control signals successfully tested."); + + $display("Testing LOAD opcode control signals..."); + + $display("Testing signals common to all instructions..."); + + opcode_6_to_2 = `OPCODE_LOAD; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WB_MUX_SEL != `WB_LU) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `I_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("LOAD control signals common to all instructions successfully tested."); + + $display("Testing load unit control signals generation..."); + + FUNCT3 = `FUNCT3_BYTE; + #10; + if(LOAD_SIZE != `LOAD_BYTE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(LOAD_UNSIGNED != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Load unit signals for LB... OK."); + + $display("Testing signal MISALIGNED_LOAD for LB..."); + + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_LOAD generation for LB OK."); + + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(LOAD_SIZE != `LOAD_HALF) + begin + $display("FAIL. Check the results."); + $finish; + end + if(LOAD_UNSIGNED != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Load unit signals for LH... OK."); + + $display("Testing signal MISALIGNED_LOAD for LH..."); + + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_LOAD generation for LH OK."); + + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(LOAD_SIZE != `LOAD_WORD) + begin + $display("FAIL. Check the results."); + $finish; + end + if(LOAD_UNSIGNED != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Load unit signals for LW... OK."); + + $display("Testing signal MISALIGNED_LOAD for LW..."); + + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_LOAD generation for LW OK."); + + FUNCT3 = `FUNCT3_BYTE_U; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(LOAD_SIZE != `LOAD_BYTE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(LOAD_UNSIGNED != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Load unit signals for LBU... OK."); + + $display("Testing signal MISALIGNED_LOAD for LBU..."); + + FUNCT3 = `FUNCT3_BYTE_U; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE_U; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE_U; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_LOAD generation for LBU OK."); + + FUNCT3 = `FUNCT3_HALF_U; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(LOAD_SIZE != `LOAD_HALF) + begin + $display("FAIL. Check the results."); + $finish; + end + if(LOAD_UNSIGNED != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Load unit signals for LHU... OK."); + + $display("Testing signal MISALIGNED_LOAD for LHU..."); + + FUNCT3 = `FUNCT3_HALF_U; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF_U; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF_U; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_LOAD != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_LOAD generation for LHU OK."); + + $display("Signals for load unit successfuly tested."); + + $display("LOAD opcode successfully tested."); + + $display("Testing STORE opcode operation..."); + + $display("Testing signals common to all instructions..."); + + opcode_6_to_2 = `OPCODE_STORE; + OPCODE = {opcode_6_to_2, 2'b11}; + IADDER_OUT_1_TO_0 = 2'b00; + + #10; + if(MEM_WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_LOAD != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `S_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + TRAP_TAKEN = 1'b1; + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + TRAP_TAKEN = 1'b0; + + $display("STORE control signals common to all instructions successfully tested."); + + $display("Testing signal MISALIGNED_STORE for SB..."); + + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_BYTE; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_STORE generation for SB OK."); + + $display("Testing signal MISALIGNED_STORE for SH..."); + + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_STORE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_HALF; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_STORE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_STORE generation for SH OK."); + + $display("Testing signal MISALIGNED_STORE for SW..."); + + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b00; + #10; + if(MISALIGNED_STORE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b01; + #10; + if(MISALIGNED_STORE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b10; + #10; + if(MISALIGNED_STORE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + FUNCT3 = `FUNCT3_WORD; + IADDER_OUT_1_TO_0 = 2'b11; + #10; + if(MISALIGNED_STORE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISALIGNED_STORE generation for SW OK."); + + $display("STORE operation successfully tested."); + + $display("Testing BRANCH opcode signals generation..."); + + opcode_6_to_2 = `OPCODE_BRANCH; + OPCODE = {opcode_6_to_2, 2'b11}; + IADDER_OUT_1_TO_0 = 2'b00; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `B_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("BRANCH control signals successfully tested."); + + $display("Testing JAL control signals generation..."); + + opcode_6_to_2 = `OPCODE_JAL; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WB_MUX_SEL != `WB_PC_PLUS) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `J_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("JAL control signals successfully tested."); + + $display("Testing JALR control signals generation..."); + + opcode_6_to_2 = `OPCODE_JALR; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + if(WB_MUX_SEL != `WB_PC_PLUS) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `I_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("JALR control signals successfully tested."); + + $display("Testing LUI opcode operation..."); + + opcode_6_to_2 = `OPCODE_LUI; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + if(WB_MUX_SEL != `WB_IMM) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `U_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("LUI control signals successfully tested."); + + $display("Testing AUIPC control signals generation..."); + + opcode_6_to_2 = `OPCODE_AUIPC; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WB_MUX_SEL != `WB_IADDER_OUT) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IADDER_SRC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `U_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("AUIPC control signals successfully tested."); + + $display("Testing MISC-MEM control signals generation..."); + + opcode_6_to_2 = `OPCODE_MISC_MEM; + OPCODE = {opcode_6_to_2, 2'b11}; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MISM-MEM control signals successfully tested."); + + $display("Testing SYSteel Core control signals operation..."); + + $display("Testing ECALL, EBREAK, MRET and WFI instructions..."); + + opcode_6_to_2 = `OPCODE_SYSTEM; + OPCODE = {opcode_6_to_2, 2'b11}; + FUNCT3 = 3'b000; + + #10; + if(MEM_WR_REQ != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("ECALL, EBREAK, MRET and WFI successfully tested."); + + $display("Testing CSRRW..."); + + FUNCT3 = 3'b001; + #10; + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `CSR_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_OP != FUNCT3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CSRRW successfully tested."); + + $display("Testing CSRRS..."); + + FUNCT3 = 3'b010; + #10; + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `CSR_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_OP != FUNCT3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CSRRS successfully tested."); + + $display("Testing CSRRC..."); + + FUNCT3 = 3'b011; + #10; + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `CSR_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_OP != FUNCT3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CSRRC successfully tested."); + + $display("Testing CSRRWI..."); + + FUNCT3 = 3'b101; + #10; + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `CSR_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_OP != FUNCT3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CSRRWI successfully tested."); + + $display("Testing CSRRSI..."); + + FUNCT3 = 3'b110; + #10; + if(ILLEGAL_INSTR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RF_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_WR_EN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(IMM_TYPE != `CSR_TYPE) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_OP != FUNCT3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CSRRSI successfully tested."); + + $display("Steel Core control signals successfully tested."); + + $display("Testing illegal instructions..."); + + OPCODE = {`OPCODE_OP,2'b10}; + #10; + if(ILLEGAL_INSTR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE = {`OPCODE_OP,2'b01}; + #10; + if(ILLEGAL_INSTR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE = {5'b11111,2'b11}; + #10; + if(ILLEGAL_INSTR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Illegal instructions successfully tested."); + + $display("Control Unit successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_csr_file.v =================================================================== --- steelcore/trunk/bench/tb_csr_file.v (nonexistent) +++ steelcore/trunk/bench/tb_csr_file.v (revision 11) @@ -0,0 +1,1971 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 30.04.2020 21:30:47 +// Module Name: tb_csr_file +// Project Name: Steel Core +// Description: RISC-V Steel Core CSR File testbench +// +// Dependencies: csr_file.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_csr_file(); + + reg CLK; + reg RESET; + + reg WR_EN; + reg [11:0] CSR_ADDR; + reg [2:0] CSR_OP; + reg [4:0] CSR_UIMM; + reg [31:0] CSR_DATA_IN; + wire [31:0] CSR_DATA_OUT; + + reg [31:0] PC; + + reg E_IRQ; + reg T_IRQ; + reg S_IRQ; + + reg I_OR_E; + reg SET_CAUSE; + reg [3:0] CAUSE_IN; + reg SET_EPC; + reg INSTRET_INC; + reg MIE_CLEAR; + reg MIE_SET; + wire MIE; + wire MEIE_OUT; + wire MTIE_OUT; + wire MSIE_OUT; + wire MEIP_OUT; + wire MTIP_OUT; + wire MSIP_OUT; + + reg [63:0] REAL_TIME; + + wire [31:0] EPC_OUT; + wire [31:0] TRAP_ADDRESS; + + csr_file dut( + + .CLK(CLK), + .RESET(RESET), + + .WR_EN(WR_EN), + .CSR_ADDR(CSR_ADDR), + .CSR_OP(CSR_OP), + .CSR_UIMM(CSR_UIMM), + .CSR_DATA_IN(CSR_DATA_IN), + .CSR_DATA_OUT(CSR_DATA_OUT), + + .PC(PC), + + .E_IRQ(E_IRQ), + .T_IRQ(T_IRQ), + .S_IRQ(S_IRQ), + + .I_OR_E(I_OR_E), + .SET_CAUSE(SET_CAUSE), + .CAUSE_IN(CAUSE_IN), + .SET_EPC(SET_EPC), + .INSTRET_INC(INSTRET_INC), + .MIE_CLEAR(MIE_CLEAR), + .MIE_SET(MIE_SET), + .MIE(MIE), + .MEIE_OUT(MEIE_OUT), + .MTIE_OUT(MTIE_OUT), + .MSIE_OUT(MSIE_OUT), + .MEIP_OUT(MEIP_OUT), + .MTIP_OUT(MTIP_OUT), + .MSIP_OUT(MSIP_OUT), + + .REAL_TIME(REAL_TIME), + + .EPC_OUT(EPC_OUT), + .TRAP_ADDRESS(TRAP_ADDRESS) + + ); + + reg [31:0] base_offset; + + always + begin + #10 CLK = !CLK; + end + + initial + begin + + $display("Testing CSR Register File..."); + + CLK = 1'b0; + RESET = 1'b0; + + WR_EN = 1'b0; + CSR_ADDR = 5'b00000; + CSR_OP = `CSR_NOP; + CSR_UIMM = 5'b00000; + CSR_DATA_IN = 32'h00000000; + PC = 32'h00000000; + E_IRQ = 1'b0; + T_IRQ = 1'b0; + S_IRQ = 1'b0; + I_OR_E = 1'b0; + SET_CAUSE = 1'b0; + CAUSE_IN = 4'b0000; + SET_EPC = 1'b0; + INSTRET_INC = 1'b0; + MIE_CLEAR = 1'b0; + MIE_SET = 1'b0; + REAL_TIME = 64'h0000000000000000; + + //---------------------------------------------------------------------- + // RESET VALUES TEST + //---------------------------------------------------------------------- + + $display("Testing values after reset..."); + + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `CYCLE; + #5; + if(CSR_DATA_OUT != `MCYCLE_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("CYCLE reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `CYCLEH; + #5; + if(CSR_DATA_OUT != `MCYCLEH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("CYCLEH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `TIME; + #5; + if(CSR_DATA_OUT != `TIME_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("TIME reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `TIMEH; + #5; + if(CSR_DATA_OUT != `TIMEH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("TIMEH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `INSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("INSTRET reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `INSTRETH; + #5; + if(CSR_DATA_OUT != `MINSTRETH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("INSTRETH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MSTATUS; + #5; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MSTATUS reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MISA; + #5; + if(CSR_DATA_OUT != 32'b01000000000000000000000100000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MISA reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MIE; + #5; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MIE reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MTVEC; + #5; + if(CSR_DATA_OUT != {`MTVEC_BASE_RESET, `MTVEC_MODE_RESET}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MTVEC reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MSCRATCH; + #5; + if(CSR_DATA_OUT != `MSCRATCH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MSCRATCH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MEPC; + #5; + if(CSR_DATA_OUT != `MEPC_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MEPC reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MTVAL; + #5; + if(CSR_DATA_OUT != 32'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MTVAL reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MIP; + #5; + if(CSR_DATA_OUT != 32'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MIP reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MCYCLE; + #5; + if(CSR_DATA_OUT != `MCYCLE_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("CYCLE reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MCYCLEH; + #5; + if(CSR_DATA_OUT != `MCYCLEH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("CYCLEH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MINSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("INSTRET reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MINSTRETH; + #5; + if(CSR_DATA_OUT != `MINSTRETH_RESET) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("INSTRETH reset value OK."); + + #20; + RESET = 1'b1; + #15; + RESET = 1'b0; + CSR_ADDR = `MCOUNTINHIBIT; + #5; + if(CSR_DATA_OUT != {29'b0, `MCOUNTINHIBIT_IR_RESET, 1'b0, `MCOUNTINHIBIT_CY_RESET}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("MCOUNTINHIBIT reset value OK."); + + $display("Reset values successfully tested."); + + #35; + + //---------------------------------------------------------------------- + // WRITE OPERATION TEST + //---------------------------------------------------------------------- + + $display("Testing write operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b0, `CSR_RW}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b1, 3'b0, 1'b1, 3'b0, 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFC) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Write operation successfully tested."); + + //---------------------------------------------------------------------- + // SET OPERATION TEST + //---------------------------------------------------------------------- + + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + $display("Testing set operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b0, `CSR_RS}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT == 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b1, 3'b0, 1'b1, 3'b0, 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFC) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Set operation successfully tested."); + + //---------------------------------------------------------------------- + // CLEAR OPERATION TEST + //---------------------------------------------------------------------- + + $display("Testing clear operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b0, `CSR_RC}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT != 32'hFFFFFFFF) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b0, 3'b0 , 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b0, 1'b0, 1'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Clear operation successfully tested."); + + //---------------------------------------------------------------------- + // WRITE IMMEDIATE OPERATION TEST + //---------------------------------------------------------------------- + + $display("Testing write immediate operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b1, `CSR_RW}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b0, 3'b0 , 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'h0000001C) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to write the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Write operation successfully tested."); + + //---------------------------------------------------------------------- + // SET IMMEDIATE OPERATION TEST + //---------------------------------------------------------------------- + + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + $display("Testing set immediate operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b1, `CSR_RS}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT == 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'h0000001C) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to set the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Set operation successfully tested."); + + //---------------------------------------------------------------------- + // CLEAR IMMEDIATE OPERATION TEST + //---------------------------------------------------------------------- + + $display("Testing clear immediate operation for each CSR..."); + + WR_EN = 1'b1; + CSR_OP = {1'b1, `CSR_RC}; + CSR_UIMM = 5'b11111; + CSR_DATA_IN = 32'hFFFFFFFF; + + CSR_ADDR = `CYCLE; + #20; + if(CSR_DATA_OUT == 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register CYCLE unsuccessful. Result OK."); + + CSR_ADDR = `CYCLEH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register CYCLEH unsuccessful. Result OK."); + + CSR_ADDR = `TIME; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register TIME unsuccessful. Result OK."); + + CSR_ADDR = `TIMEH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register TIMEH unsuccessful. Result OK."); + + CSR_ADDR = `INSTRET; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register INSTRET unsuccessful. Result OK."); + + CSR_ADDR = `INSTRETH; + #20; + if(CSR_DATA_OUT != 32'h0000001F) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register INSTRETH unsuccessful. Result OK."); + + CSR_ADDR = `MSTATUS; + #20; + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MSTATUS successful. Result OK."); + + CSR_ADDR = `MISA; + #20; + if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MISA unsuccessful. Result OK."); + + CSR_ADDR = `MIE; + #20; + if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MIE successful. Result OK."); + + CSR_ADDR = `MTVEC; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MTVEC successful. Result OK."); + + CSR_ADDR = `MSCRATCH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MSCRATCH successful. Result OK."); + + CSR_ADDR = `MEPC; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MEPC successful. Result OK."); + + CSR_ADDR = `MCAUSE; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MCAUSE unsuccessful. Result OK."); + + CSR_ADDR = `MTVAL; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MTVAL unsuccessful. Result OK."); + + CSR_ADDR = `MIP; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-only register MIP unsuccessful. Result OK."); + + CSR_ADDR = `MCYCLE; + #20; + if(CSR_DATA_OUT != 32'h00000020) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCYCLE successful. Result OK."); + + CSR_ADDR = `MCYCLEH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCYCLEH successful. Result OK."); + + CSR_ADDR = `MINSTRET; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MINSTRET successful. Result OK."); + + CSR_ADDR = `MINSTRETH; + #20; + if(CSR_DATA_OUT != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MINSTRETH successful. Result OK."); + + CSR_ADDR = `MCOUNTINHIBIT; + #20; + if(CSR_DATA_OUT != {29'b0, 1'b0, 1'b0, 1'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("Attempt to clear the read-write register MCOUNTINHIBIT successful. Result OK."); + + $display("Clear operation successfully tested."); + + //---------------------------------------------------------------------- + // INTERRUPT PENDING BITS TEST + //---------------------------------------------------------------------- + + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + $display("Testing interrupt pending bits setup..."); + + E_IRQ = 1'b1; + T_IRQ = 1'b1; + S_IRQ = 1'b1; + #20; + + if(MEIP_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MTIP_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MSIP_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Interrupt pending bits successfully tested."); + + //---------------------------------------------------------------------- + // INTERRUPT ENABLE BITS TEST + //---------------------------------------------------------------------- + + $display("Testing interrupt enable bits setup..."); + + WR_EN = 1'b1; + CSR_ADDR = `MSTATUS; + CSR_DATA_IN = 32'hFFFFFFFF; + CSR_OP = {1'b0, `CSR_RW}; + #20; + WR_EN = 1'b1; + CSR_ADDR = `MIE; + CSR_DATA_IN = 32'hFFFFFFFF; + CSR_OP = {1'b0, `CSR_RW}; + #20; + + if(MIE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MEIE_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MTIE_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MSIE_OUT != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Interrupt enable bits successfully tested."); + + //---------------------------------------------------------------------- + // EPC SET TEST + //---------------------------------------------------------------------- + + $display("Testing EPC setup..."); + + SET_EPC = 1'b1; + PC = $random; + CSR_ADDR = `MEPC; + #20; + SET_EPC = 1'b0; + + if(CSR_DATA_OUT != PC) + begin + $display("FAIL. Check the results."); + $finish; + end + if(EPC_OUT != PC) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("EPC setup successfully tested."); + + //---------------------------------------------------------------------- + // MCAUSE SET TEST + //---------------------------------------------------------------------- + + $display("Testing MCAUSE setup..."); + + SET_CAUSE = 1'b1; + CAUSE_IN = $random; + I_OR_E = 1'b1; + CSR_ADDR = `MCAUSE; + #20; + + if(CSR_DATA_OUT != {I_OR_E, 27'b0, CAUSE_IN}) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MCAUSE setup successfully tested."); + + //---------------------------------------------------------------------- + // TRAP ADDRESS GENERATION TEST + //---------------------------------------------------------------------- + + $display("Testing TRAP ADDRESS generation..."); + + $display("Testing exceptions in Direct Mode..."); + WR_EN =1'b1; + CSR_ADDR = `MTVEC; + CSR_OP = {1'b0, `CSR_RW}; + CSR_DATA_IN = $random; + CSR_DATA_IN[1:0] = 2'b00; + SET_CAUSE = 1'b1; + CAUSE_IN = $random; + I_OR_E = 1'b0; + #20; + + if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Exceptions in Direct Mode OK."); + + $display("Testing interrupts in Direct Mode..."); + WR_EN =1'b1; + CSR_ADDR = `MTVEC; + CSR_OP = {1'b0, `CSR_RW}; + CSR_DATA_IN = $random; + CSR_DATA_IN[1:0] = 2'b00; + SET_CAUSE = 1'b1; + CAUSE_IN = $random; + I_OR_E = 1'b1; + #20; + + if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Interrupts in Direct Mode OK."); + + $display("Testing exceptions in Vectored Mode..."); + WR_EN =1'b1; + CSR_ADDR = `MTVEC; + CSR_OP = {1'b0, `CSR_RW}; + CSR_DATA_IN = $random; + CSR_DATA_IN[1:0] = 2'b01; + SET_CAUSE = 1'b1; + CAUSE_IN = $random; + I_OR_E = 1'b0; + #20; + + if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b01}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Exceptions in Vectored Mode OK."); + + $display("Testing interrupts in Vectored Mode..."); + WR_EN =1'b1; + CSR_ADDR = `MTVEC; + CSR_OP = {1'b0, `CSR_RW}; + CSR_DATA_IN = $random; + CSR_DATA_IN[1:0] = 2'b01; + SET_CAUSE = 1'b1; + CAUSE_IN = $random; + I_OR_E = 1'b1; + #20; + + if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b01}) + begin + $display("FAIL. Check the results."); + $finish; + end + base_offset = CAUSE_IN << 2; + if(TRAP_ADDRESS != ({CSR_DATA_IN[31:2],2'b00} + base_offset)) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Interrupts in Vectored Mode OK."); + + $display("TRAP ADDRESS generation successfully tested."); + + //---------------------------------------------------------------------- + // MIE CLEAR & SET TEST + //---------------------------------------------------------------------- + + WR_EN =1'b0; + + $display("Testing MIE clear operation..."); + + MIE_CLEAR = 1'b1; + CSR_ADDR = `MSTATUS; + #20; + MIE_CLEAR = 1'b0; + + if(MIE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + + MIE_SET = 1'b1; + CSR_ADDR = `MSTATUS; + #20; + MIE_SET = 1'b0; + + if(MIE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("MIE CLEAR & SET operation successfully tested."); + + //---------------------------------------------------------------------- + // CYCLE & INSTRET COUNTING TEST + //---------------------------------------------------------------------- + + WR_EN =1'b0; + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + $display("Testing CYCLE and INSTRET counting..."); + + INSTRET_INC = 1'b1; + CSR_ADDR = `CYCLE; + #15; + + if(CSR_DATA_OUT != `MCYCLE_RESET + 1) + begin + $display("FAIL. Check the results."); + $finish; + end + CSR_ADDR = `INSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET + 1) + begin + $display("FAIL. Check the results."); + $finish; + end + + INSTRET_INC = 1'b0; + CSR_ADDR = `CYCLE; + #15; + + if(CSR_DATA_OUT != `MCYCLE_RESET + 2) + begin + $display("FAIL. Check the results."); + $finish; + end + CSR_ADDR = `INSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET + 1) + begin + $display("FAIL. Check the results."); + $finish; + end + + WR_EN = 1'b1; + INSTRET_INC = 1'b1; + CSR_OP = {1'b0, CSR_OP}; + CSR_ADDR = `MCOUNTINHIBIT; + CSR_DATA_IN = {29'b0, 3'b101}; + #20; + + WR_EN = 1'b0; + CSR_ADDR = `CYCLE; + #15; + + if(CSR_DATA_OUT != `MCYCLE_RESET + 3) + begin + $display("FAIL. Check the results."); + $finish; + end + CSR_ADDR = `INSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET + 2) + begin + $display("FAIL. Check the results."); + $finish; + end + + WR_EN = 1'b1; + CSR_OP = {1'b0, CSR_OP}; + CSR_ADDR = `MCOUNTINHIBIT; + CSR_DATA_IN = {29'b0, 3'b000}; + #20; + + WR_EN = 1'b0; + CSR_ADDR = `CYCLE; + #15; + + if(CSR_DATA_OUT != `MCYCLE_RESET + 4) + begin + $display("FAIL. Check the results."); + $finish; + end + CSR_ADDR = `INSTRET; + #5; + if(CSR_DATA_OUT != `MINSTRET_RESET + 3) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("CYCLE & INSTRET counting successfully tested."); + + $display("CSR Register File successfully tested."); + + end + +endmodule + Index: steelcore/trunk/bench/tb_imm_generator.v =================================================================== --- steelcore/trunk/bench/tb_imm_generator.v (nonexistent) +++ steelcore/trunk/bench/tb_imm_generator.v (revision 11) @@ -0,0 +1,298 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 22:58:58 +// Module Name: tb_imm_generator +// Project Name: Steel Core +// Description: RISC-V Steel Core Immediate Generator testbench +// +// Dependencies: imm_generator.v, control_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_imm_generator(); + + reg [31:0] INSTR; + reg [2:0] FUNCT3; + wire [2:0] IMM_TYPE; + wire [31:0] IMM; + + imm_generator dut( + + .INSTR(INSTR[31:7]), + .IMM_TYPE(IMM_TYPE), + .IMM(IMM) + + ); + + control_unit ctrlunit( + + .OPCODE(INSTR[6:0]), + .FUNCT7_5(1'b0), + .FUNCT3(FUNCT3), + .IMM_TYPE(IMM_TYPE) + + ); + + integer i; + + initial + begin + + $display("Testing Immediate Generator..."); + + INSTR = {30'b0, 2'b11}; + FUNCT3 = 3'b0; + + $display("Testing immediate generator for OP-IMM opcode"); + + INSTR[6:2] = `OPCODE_OP_IMM; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {20{INSTR[31]}}, INSTR[31:20] }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("OP-IMM opcode successfully tested."); + + $display("Testing immediate generator for LOAD opcode"); + + INSTR[6:2] = `OPCODE_LOAD; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {20{INSTR[31]}}, INSTR[31:20] }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("LOAD opcode successfully tested."); + + $display("Testing immediate generator for STORE opcode"); + + INSTR[6:2] = `OPCODE_STORE; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {20{INSTR[31]}}, INSTR[31:25], INSTR[11:7] }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("STORE opcode successfully tested."); + + $display("Testing immediate generator for BRANCH opcode"); + + INSTR[6:2] = `OPCODE_BRANCH; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {19{INSTR[31]}}, INSTR[31], INSTR[7], INSTR[30:25], INSTR[11:8], 1'b0 }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("BRANCH opcode successfully tested."); + + $display("Testing immediate generator for JALR opcode"); + + INSTR[6:2] = `OPCODE_JALR; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {20{INSTR[31]}}, INSTR[31:20] }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("JALR opcode successfully tested."); + + $display("Testing immediate generator for JAL opcode"); + + INSTR[6:2] = `OPCODE_JAL; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { {11{INSTR[31]}}, INSTR[31], INSTR[19:12], INSTR[20], INSTR[30:21], 1'b0 }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("JAL opcode successfully tested."); + + $display("Testing immediate generator for LUI opcode"); + + INSTR[6:2] = `OPCODE_LUI; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { INSTR[31:12], 12'h000 }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("LUI opcode successfully tested."); + + $display("Testing immediate generator for AUIPC opcode"); + + INSTR[6:2] = `OPCODE_AUIPC; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + + #10; + + if(IMM != { INSTR[31:12], 12'h000 }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("AUIPC opcode successfully tested."); + + $display("Testing immediate generator for SYSteel Core opcode"); + + INSTR[6:2] = `OPCODE_SYSTEM; + + for(i = 0; i < 10000; i=i+1) + begin + + INSTR[31:7] = $random; + FUNCT3 = $random; + + #10; + + if(FUNCT3 != 3'b000 && IMM != { 27'b0, INSTR[19:15] }) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("SYSteel Core opcode successfully tested."); + + $display("Immediate Generator successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_integer_file.v =================================================================== --- steelcore/trunk/bench/tb_integer_file.v (nonexistent) +++ steelcore/trunk/bench/tb_integer_file.v (revision 11) @@ -0,0 +1,199 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 03.04.2020 18:35:35 +// Module Name: tb_integer_file +// Project Name: Steel Core +// Description: RISC-V Steel Core 32-bit Integer Register File testbench +// +// Dependencies: register_file.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_integer_file(); + + reg CLK; + reg RESET; + + reg [4:0] RS_1_ADDR; + reg [4:0] RS_2_ADDR; + wire [31:0] RS_1; + wire [31:0] RS_2; + + reg [4:0] RD_ADDR; + reg WR_EN; + reg [31:0] RD; + + integer_file dut( + + .CLK( CLK), + .RESET( RESET), + + .RS_1_ADDR( RS_1_ADDR), + .RS_2_ADDR( RS_2_ADDR), + .RD_ADDR( RD_ADDR), + .RS_1( RS_1), + .RS_2( RS_2), + + .WR_EN( WR_EN), + .RD( RD) + + ); + + integer i; + + always + begin + #10 CLK = !CLK; + end + + initial + begin + + $display("Testing Integer Register File..."); + + CLK = 1'b0; + RESET = 1'b0; + + RS_1_ADDR = 5'b00000; + RS_2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + WR_EN = 1'b0; + RD = 32'b0; + + #5; + + RESET = 1'b1; + + #15; + + RESET = 1'b0; + + $display("Testing values after reset..."); + + for(i = 0; i < 32; i=i+1) + begin + + RS_1_ADDR = i[4:0]; + + #20; + + if(RS_1 != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("Reset values OK."); + + $display("Testing write operation..."); + + for(i = 0; i < 32; i=i+1) + begin + + RD_ADDR = i[4:0]; + WR_EN = 1'b1; + RD = $random; + + #20; + + WR_EN = 1'b0; + RS_1_ADDR = RD_ADDR; + RS_2_ADDR = RD_ADDR; + + #20; + + if(RD_ADDR == 5'b00000) + begin + if(RS_1 != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RS_2 != 32'h00000000) + begin + $display("FAIL. Check the results."); + $finish; + end + end + if(RD_ADDR != 5'b00000) + begin + if(RS_1 != RD) + begin + $display("FAIL. Check the results."); + $finish; + end + if(RS_2 != RD) + begin + $display("FAIL. Check the results."); + $finish; + end + end + + end + + $display("Write operation seems to work."); + + $display("Integer Register File successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_load_unit.v =================================================================== --- steelcore/trunk/bench/tb_load_unit.v (nonexistent) +++ steelcore/trunk/bench/tb_load_unit.v (revision 11) @@ -0,0 +1,252 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 20:52:25 +// Module Name: tb_load_unit +// Project Name: Steel Core +// Description: RISC-V Steel Core Load Unit testbench +// +// Dependencies: load_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + + +module tb_load_unit(); + + reg [1:0] LOAD_SIZE; + reg LOAD_UNSIGNED; + reg [31:0] DATA_IN; + reg [1:0] IADDER_OUT_1_TO_0; + wire [31:0] OUTPUT; + + load_unit dut( + + .LOAD_SIZE(LOAD_SIZE), + .LOAD_UNSIGNED(LOAD_UNSIGNED), + .DATA_IN(DATA_IN), + .IADDER_OUT_1_TO_0(IADDER_OUT_1_TO_0), + .OUTPUT(OUTPUT) + + ); + + integer i; + + initial + begin + + $display("Testing Load Unit..."); + + $display("Testing Load Unit for LB operation."); + LOAD_SIZE = 2'b00; + LOAD_UNSIGNED = 1'b0; + + for(i = 0; i < 10000; i=i+1) + begin + + DATA_IN = $random; + IADDER_OUT_1_TO_0 = $random; + + #10; + + if(IADDER_OUT_1_TO_0 == 2'b00 & OUTPUT != { {24{DATA_IN[7]}} , DATA_IN[7:0]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b01 & OUTPUT != { {24{DATA_IN[15]}} , DATA_IN[15:8]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b10 & OUTPUT != { {24{DATA_IN[23]}} , DATA_IN[23:16]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b11 & OUTPUT != { {24{DATA_IN[31]}} , DATA_IN[31:24]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + + end + + $display("LB operation successfully tested."); + + $display("Testing Load Unit for LH operation."); + LOAD_SIZE = 2'b01; + LOAD_UNSIGNED = 1'b0; + + for(i = 0; i < 10000; i=i+1) + begin + + DATA_IN = $random; + IADDER_OUT_1_TO_0 = $random; + IADDER_OUT_1_TO_0[0] = 1'b0; + + #10; + + if(IADDER_OUT_1_TO_0[1] == 1'b0 & OUTPUT != { {16{DATA_IN[15]}} , DATA_IN[15:0]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0[1] == 1'b1 & OUTPUT != { {16{DATA_IN[31]}} , DATA_IN[31:16]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + + end + + $display("LH operation successfully tested."); + + $display("Testing Load Unit for LW operation."); + LOAD_SIZE = 2'b10; + LOAD_UNSIGNED = 1'b0; + + for(i = 0; i < 10000; i=i+1) + begin + + DATA_IN = $random; + IADDER_OUT_1_TO_0 = 2'b00; + + #10; + + if(OUTPUT != DATA_IN[31:0]) + begin + $display("FAIL. Wrong result."); + $finish; + end + + end + + $display("LW operation successfully tested."); + + $display("Testing Load Unit for LBU operation."); + LOAD_SIZE = 2'b00; + LOAD_UNSIGNED = 1'b1; + + for(i = 0; i < 10000; i=i+1) + begin + + DATA_IN = $random; + IADDER_OUT_1_TO_0 = $random; + + #10; + + if(IADDER_OUT_1_TO_0 == 2'b00 & OUTPUT != { 24'b0 , DATA_IN[7:0]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b01 & OUTPUT != { 24'b0 , DATA_IN[15:8]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b10 & OUTPUT != { 24'b0 , DATA_IN[23:16]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0 == 2'b11 & OUTPUT != { 24'b0 , DATA_IN[31:24]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + + end + + $display("LBU operation successfully tested."); + + $display("Testing Load Unit for LHU operation."); + + LOAD_SIZE = 2'b01; + LOAD_UNSIGNED = 1'b1; + + for(i = 0; i < 10000; i=i+1) + begin + + DATA_IN = $random; + IADDER_OUT_1_TO_0 = $random; + IADDER_OUT_1_TO_0[0] = 1'b0; + + #10; + + if(IADDER_OUT_1_TO_0[1] == 1'b0 & OUTPUT != { 16'b0 , DATA_IN[15:0]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + else if(IADDER_OUT_1_TO_0[1] == 1'b1 & OUTPUT != { 16'b0 , DATA_IN[31:16]}) + begin + $display("FAIL. Wrong result."); + $finish; + end + + end + + $display("LHU operation successfully tested."); + + $display("Load Unit successfully tested."); + + end + +endmodule Index: steelcore/trunk/bench/tb_machine_mode.v =================================================================== --- steelcore/trunk/bench/tb_machine_mode.v (nonexistent) +++ steelcore/trunk/bench/tb_machine_mode.v (revision 11) @@ -0,0 +1,1528 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 02.05.2020 15:45:27 +// Module Name: tb_machine_mode +// Project Name: Steel Core +// Description: RISC-V Steel Core Machine Mode testbench +// +// Dependencies: csr_file.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_machine_mode(); + + reg CLK; + reg RESET; + + reg ILLEGAL_INSTR; + reg MISALIGNED_INSTR; + reg MISALIGNED_LOAD; + reg MISALIGNED_STORE; + + reg [6:2] OPCODE_6_TO_2; + reg [2:0] FUNCT3; + reg [6:0] FUNCT7; + reg [4:0] RS1_ADDR; + reg [4:0] RS2_ADDR; + reg [4:0] RD_ADDR; + + reg E_IRQ; + reg T_IRQ; + reg S_IRQ; + + reg MIE; + reg MEIE; + reg MTIE; + reg MSIE; + reg MEIP; + reg MTIP; + reg MSIP; + + wire I_OR_E; + wire SET_EPC; + wire SET_CAUSE; + wire [3:0] CAUSE; + wire INSTRET_INC; + wire MIE_CLEAR; + wire MIE_SET; + + wire [1:0] PC_SRC; + + wire FLUSH; + + wire TRAP_TAKEN; + + machine_control dut( + + .CLK(CLK), + .RESET(RESET), + + .ILLEGAL_INSTR(ILLEGAL_INSTR), + .MISALIGNED_INSTR(MISALIGNED_INSTR), + .MISALIGNED_LOAD(MISALIGNED_LOAD), + .MISALIGNED_STORE(MISALIGNED_STORE), + + .OPCODE_6_TO_2(OPCODE_6_TO_2), + .FUNCT3(FUNCT3), + .FUNCT7(FUNCT7), + .RS1_ADDR(RS1_ADDR), + .RS2_ADDR(RS2_ADDR), + .RD_ADDR(RD_ADDR), + + .E_IRQ(E_IRQ), + .T_IRQ(T_IRQ), + .S_IRQ(S_IRQ), + + .I_OR_E(I_OR_E), + .SET_CAUSE(SET_CAUSE), + .CAUSE(CAUSE), + .SET_EPC(SET_EPC), + .INSTRET_INC(INSTRET_INC), + .MIE_CLEAR(MIE_CLEAR), + .MIE_SET(MIE_SET), + .MIE(MIE), + .MEIE(MEIE), + .MTIE(MTIE), + .MSIE(MSIE), + .MEIP(MEIP), + .MTIP(MTIP), + .MSIP(MSIP), + + .PC_SRC(PC_SRC), + + .FLUSH(FLUSH), + + .TRAP_TAKEN(TRAP_TAKEN) + + ); + + always + begin + #10 CLK = !CLK; + end + + initial + begin + + $display("Testing Machine Mode Control module..."); + + CLK = 1'b0; + RESET = 1'b0; + + ILLEGAL_INSTR = 1'b0; + MISALIGNED_INSTR = 1'b0; + MISALIGNED_LOAD = 1'b0; + MISALIGNED_STORE = 1'b0; + + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + + E_IRQ = 1'b0; + T_IRQ = 1'b0; + S_IRQ = 1'b0; + + MIE = 1'b0; + MEIE = 1'b0; + MTIE = 1'b0; + MSIE = 1'b0; + MEIP = 1'b0; + MTIP = 1'b0; + MSIP = 1'b0; + + $display("Testing RESET state..."); + + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + if(PC_SRC != `PC_BOOT) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_SET != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("RESET state values OK."); + + #20; + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing OPERATING state..."); + + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_SET != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + $display("OPERATING state values OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine keeps in operating state when MIE=0 for all kinds of interrupt..."); + + E_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + + T_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + + S_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine changes it state when MIE=0 for all kinds of exceptions."); + + MIE = 1'b0; + ILLEGAL_INSTR = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0010) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + ILLEGAL_INSTR = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_INSTR = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0000) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_INSTR = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_LOAD = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0100) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_LOAD = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_STORE = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0110) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_STORE = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_SYSTEM; + FUNCT3 = `FUNCT3_ECALL; + FUNCT7 = `FUNCT7_ECALL; + RS1_ADDR = `RS1_ECALL; + RS2_ADDR = `RS2_ECALL; + RD_ADDR = `RD_ECALL; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b1011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_SYSTEM; + FUNCT3 = `FUNCT3_EBREAK; + FUNCT7 = `FUNCT7_EBREAK; + RS1_ADDR = `RS1_EBREAK; + RS2_ADDR = `RS2_EBREAK; + RD_ADDR = `RD_EBREAK; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine keeps in operating state when MIE=1 for all types of interrupt when MTIE=0, MSIE=0 and MEIE=0..."); + + MIE = 1'b1; + E_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + + T_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + + S_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for external interrupts in operating state when MIE=1 and MTIE=0, MSIE=0 and MEIE=1..."); + + MIE = 1'b1; + MEIE = 1'b1; + E_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b1011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + T_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + + S_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + + MEIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for timer interrupts in operating state when MIE=1 and MTIE=1, MSIE=0 and MEIE=0..."); + + MIE = 1'b1; + MTIE = 1'b1; + T_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0111) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + E_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + + S_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + + MTIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for software interrupts in operating state when MIE=1 and MTIE=0, MSIE=1 and MEIE=0..."); + + MIE = 1'b1; + MSIE = 1'b1; + S_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + T_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + + E_IRQ = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + + MSIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for MEIP in operating state when MIE=1 and MTIE=0, MSIE=0 and MEIE=1..."); + + MIE = 1'b1; + MEIE = 1'b1; + MEIP = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b1011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MEIP = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MTIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MTIP = 1'b0; + + MSIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MSIP = 1'b0; + + MEIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for MTIP in operating state when MIE=1 and MTIE=1, MSIE=0 and MEIE=0..."); + + MIE = 1'b1; + MTIE = 1'b1; + MTIP = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0111) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MTIP = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MEIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MEIP = 1'b0; + + MSIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MSIP = 1'b0; + + MTIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing if the machine change its state only for MSIP in operating state when MIE=1 and MTIE=0, MSIE=1 and MEIE=0..."); + + MIE = 1'b1; + MSIE = 1'b1; + MSIP = 1'b1; + #20; + if(PC_SRC != `PC_TRAP) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(CAUSE != 4'b0011) + begin + $display("FAIL. Check the results."); + $finish; + end + if(I_OR_E != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + MSIP = 1'b0; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + + MTIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MTIP = 1'b0; + + MEIP = 1'b1; + #20; + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + MEIP = 1'b0; + + MSIE = 1'b0; + + $display("Test OK."); + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing transition from OPERATING to TRAP RETURN..."); + + OPCODE_6_TO_2 = `OPCODE_SYSTEM; + FUNCT7 = `FUNCT7_MRET; + FUNCT3 = `FUNCT3_MRET; + RS1_ADDR = `RS1_MRET; + RS2_ADDR = `RS2_MRET; + RD_ADDR = `RD_MRET; + #20; + + if(PC_SRC != `PC_EPC) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_SET != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Test OK."); + + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + + /************************************************************ + ************************************************************* + ************************************************************/ + + $display("Testing transition from TRAP RETURN to OPERATING..."); + + if(PC_SRC != `PC_NEXT) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_CAUSE != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(SET_EPC != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_CLEAR != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(MIE_SET != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(FLUSH != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + if(INSTRET_INC != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Test OK."); + + $display("Testing TRAP_TAKEN signal..."); + + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_SYSTEM; + FUNCT3 = `FUNCT3_EBREAK; + FUNCT7 = `FUNCT7_EBREAK; + RS1_ADDR = `RS1_EBREAK; + RS2_ADDR = `RS2_EBREAK; + RD_ADDR = `RD_EBREAK; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_SYSTEM; + FUNCT3 = `FUNCT3_ECALL; + FUNCT7 = `FUNCT7_ECALL; + RS1_ADDR = `RS1_ECALL; + RS2_ADDR = `RS2_ECALL; + RD_ADDR = `RD_ECALL; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + + OPCODE_6_TO_2 = `OPCODE_OP; + FUNCT3 = `FUNCT3_ADD; + FUNCT7 = `FUNCT7_ADD; + RS1_ADDR = 5'b00000; + RS2_ADDR = 5'b00000; + RD_ADDR = 5'b00000; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + ILLEGAL_INSTR = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + ILLEGAL_INSTR = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_INSTR = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_INSTR = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_LOAD = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_LOAD = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MISALIGNED_STORE = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MISALIGNED_STORE = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MIE = 1'b1; + MEIE = 1'b1; + MTIE = 1'b1; + MSIE = 1'b1; + + E_IRQ = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + E_IRQ = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + T_IRQ = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + T_IRQ = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + S_IRQ = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + S_IRQ = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MEIP = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MEIP = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MTIP = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MTIP = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + MSIP = 1'b1; + #20; + + if(TRAP_TAKEN != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + MSIP = 1'b0; + #20; + + if(TRAP_TAKEN != 1'b0) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("Machine Mode Control module successfully tested."); + + end + +endmodule + Index: steelcore/trunk/bench/tb_steel_top.v =================================================================== --- steelcore/trunk/bench/tb_steel_top.v (nonexistent) +++ steelcore/trunk/bench/tb_steel_top.v (revision 11) @@ -0,0 +1,181 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 20:52:25 +// Module Name: tb_steel_top +// Project Name: Steel Core +// Description: RISC-V Steel Core testbench +// +// Dependencies: load_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "../globals.vh" + +module tb_steel_top(); + + reg CLK; + reg RESET; + wire [31:0] I_ADDR; + reg [31:0] INSTR; + wire [31:0] D_ADDR; + wire [31:0] DATA_OUT; + wire WR_REQ; + wire [3:0] WR_MASK; + reg [31:0] DATA_IN; + reg E_IRQ; + reg T_IRQ; + reg S_IRQ; + + steel_top dut( + + .CLK(CLK), + .RESET(RESET), + .REAL_TIME(64'b0), + .I_ADDR(I_ADDR), + .INSTR(INSTR), + .D_ADDR(D_ADDR), + .DATA_OUT(DATA_OUT), + .WR_REQ(WR_REQ), + .WR_MASK(WR_MASK), + .DATA_IN(DATA_IN), + .E_IRQ(E_IRQ), + .T_IRQ(T_IRQ), + .S_IRQ(S_IRQ) + + ); + + reg [7:0] ram [0:65535]; // 8KB RAM + integer i; + integer f; + wire [12:0] eff_i_addr; + wire [12:0] eff_d_addr; + + assign eff_i_addr = I_ADDR[12:0]; + assign eff_d_addr = D_ADDR[12:0]; + + always + begin + #10 CLK = !CLK; + end + + initial + begin + + f = $fopen("../../../../../mem/mret.txt","w"); + + // LOADS PROGRAM INTO MEMORY + for(i = 0; i < 65535; i=i+1) ram[i] = 8'b0; + $readmemh("mret.mem",ram); + + // INITIAL VALUES + RESET = 1'b0; + CLK = 1'b0; + E_IRQ = 1'b0; + T_IRQ = 1'b0; + S_IRQ = 1'b0; + + // RESET + #5; + RESET = 1'b1; + #15; + RESET = 1'b0; + + #800; + + $fwrite(f, "%d", ram[1024]); + $fclose(f); + + $stop; + + end + + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + INSTR = {ram[eff_i_addr+3],ram[eff_i_addr+2],ram[eff_i_addr+1],ram[eff_i_addr]}; + DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]}; + end + else + begin + INSTR = {ram[eff_i_addr+3],ram[eff_i_addr+2],ram[eff_i_addr+1],ram[eff_i_addr]}; + DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]}; + if(WR_REQ) + begin + ram[eff_d_addr] <= DATA_OUT[7:0]; + if(WR_MASK[1]) + begin + ram[eff_d_addr+1] <= DATA_OUT[15:8]; + end + if(WR_MASK[2]) + begin + ram[eff_d_addr+2] <= DATA_OUT[23:16]; + end + if(WR_MASK[3]) + begin + ram[eff_d_addr+3] <= DATA_OUT[31:24]; + end + end + else + begin + DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]}; + end + end + end + +endmodule Index: steelcore/trunk/bench/tb_store_unit.v =================================================================== --- steelcore/trunk/bench/tb_store_unit.v (nonexistent) +++ steelcore/trunk/bench/tb_store_unit.v (revision 11) @@ -0,0 +1,297 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 02.06.2020 16:03:55 +// Module Name: tb_store_unit +// Project Name: Steel Core +// Description: RISC-V Steel Core Store Unit testbench +// +// Dependencies: store_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + + +module tb_store_unit(); + + reg [2:0] FUNCT3; + reg [31:0] IADDER_OUT; + reg [31:0] RS2; + reg MEM_WR_REQ; + wire [31:0] DATA_OUT; + wire [31:0] D_ADDR; + wire [3:0] WR_MASK; + wire WR_REQ; + + store_unit dut( + + .FUNCT3(FUNCT3[1:0]), + .IADDER_OUT(IADDER_OUT), + .RS2(RS2), + .MEM_WR_REQ(MEM_WR_REQ), + .DATA_OUT(DATA_OUT), + .D_ADDR(D_ADDR), + .WR_MASK(WR_MASK), + .WR_REQ(WR_REQ) + + ); + + integer i; + + initial + begin + + FUNCT3 = `FUNCT3_BYTE; + RS2 = $random; + MEM_WR_REQ = 1'b0; + + $display("Testing D_ADDR generation..."); + + for(i = 0; i < 20; i=i+1) + begin + + IADDER_OUT = $random; + + #10; + + if(D_ADDR != {IADDER_OUT[31:2], 2'b00}) + begin + $display("FAIL. Check the results."); + $finish; + end + + end + + $display("D_ADDR generation OK."); + + $display("Testing SB signals generation..."); + + FUNCT3 = `FUNCT3_BYTE; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b00; + + #10; + + if(DATA_OUT != {24'b0, RS2[7:0]}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b0001) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT3 = `FUNCT3_BYTE; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b01; + + #10; + + if(DATA_OUT != {16'b0, RS2[7:0], 8'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b0010) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT3 = `FUNCT3_BYTE; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b10; + + #10; + + if(DATA_OUT != {8'b0, RS2[7:0], 16'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b0100) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT3 = `FUNCT3_BYTE; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b11; + + #10; + + if(DATA_OUT != {RS2[7:0], 24'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b1000) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("SB signals generation successfully tested."); + + $display("Testing SH signals generation..."); + + FUNCT3 = `FUNCT3_HALF; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b00; + + #10; + + if(DATA_OUT != {16'b0, RS2[15:0]}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b0011) + begin + $display("FAIL. Check the results."); + $finish; + end + + FUNCT3 = `FUNCT3_HALF; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b10; + + #10; + + if(DATA_OUT != {RS2[15:0], 16'b0}) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b1100) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("SH signals generation successfully tested."); + + $display("Testing SW signals generation..."); + + FUNCT3 = `FUNCT3_WORD; + RS2 = $random; + MEM_WR_REQ = 1'b1; + IADDER_OUT[1:0] = 2'b00; + + #10; + + if(DATA_OUT != RS2) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_REQ != 1'b1) + begin + $display("FAIL. Check the results."); + $finish; + end + if(WR_MASK != 4'b1111) + begin + $display("FAIL. Check the results."); + $finish; + end + + $display("SW signals generation successfully tested."); + + end + +endmodule Index: steelcore/trunk/alu.v =================================================================== --- steelcore/trunk/alu.v (nonexistent) +++ steelcore/trunk/alu.v (revision 11) @@ -0,0 +1,116 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 30.03.2020 17:28:42 +// Module Name: alu +// Project Name: Steel Core +// Description: 32-bit Arithmetic and Logic Unit +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module alu( + + input wire [31:0] OP_1, + input wire [31:0] OP_2, + input wire [3:0] OPCODE, + output reg [31:0] RESULT + + ); + + wire signed [31:0] signed_op1; + wire signed [31:0] adder_op2; + wire [31:0] minus_op2; + wire [31:0] sra_result; + wire [31:0] srl_result; + wire [31:0] shr_result; + wire slt_result; + wire sltu_result; + + reg [31:0] pre_result; + + assign signed_op1 = OP_1; + assign minus_op2 = -OP_2; + assign adder_op2 = OPCODE[3] == 1'b1 ? minus_op2 : OP_2; + assign sra_result = signed_op1 >>> OP_2[4:0]; + assign srl_result = OP_1 >> OP_2[4:0]; + assign shr_result = OPCODE[3] == 1'b1 ? sra_result : srl_result; + assign sltu_result = OP_1 < OP_2; + assign slt_result = OP_1[31] ^ OP_2[31] ? OP_1[31] : sltu_result; + + always @* + begin + + case(OPCODE[2:0]) + + `FUNCT3_ADD: RESULT = OP_1 + adder_op2; + `FUNCT3_SRL: RESULT = shr_result; + `FUNCT3_OR: RESULT = OP_1 | OP_2; + `FUNCT3_AND: RESULT = OP_1 & OP_2; + `FUNCT3_XOR: RESULT = OP_1 ^ OP_2; + `FUNCT3_SLT: RESULT = {31'b0, slt_result}; + `FUNCT3_SLTU: RESULT = {31'b0, sltu_result}; + `FUNCT3_SLL: RESULT = OP_1 << OP_2[4:0]; + + endcase + + end + +endmodule Index: steelcore/trunk/branch_unit.v =================================================================== --- steelcore/trunk/branch_unit.v (nonexistent) +++ steelcore/trunk/branch_unit.v (revision 11) @@ -0,0 +1,120 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 18:29:52 +// Module Name: branch_unit +// Project Name: Steel Core +// Description: RISC-V Steel Core Branch Decision Unit +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module branch_unit( + + input wire [6:2] OPCODE_6_TO_2, + input wire [2:0] FUNCT3, + input wire [31:0] RS1, + input wire [31:0] RS2, + output wire BRANCH_TAKEN + + ); + + wire pc_mux_sel; + wire pc_mux_sel_en; + wire is_branch; + wire is_jal; + wire is_jalr; + wire is_jump; + wire eq; + wire ne; + wire lt; + wire ge; + wire ltu; + wire geu; + reg take; + + assign is_jal = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & OPCODE_6_TO_2[3] & OPCODE_6_TO_2[2]; + assign is_jalr = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & OPCODE_6_TO_2[2]; + assign is_jump = is_jal | is_jalr; + assign eq = (RS1 == RS2); + assign ne = !eq; + assign lt = RS1[31] ^ RS2[31] ? RS1[31] : ltu; + assign ge = !lt; + assign ltu = (RS1 < RS2); + assign geu = !ltu; + assign is_branch = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & ~OPCODE_6_TO_2[2]; + assign pc_mux_sel_en = is_branch | is_jal | is_jalr; + assign pc_mux_sel = (is_jump == 1'b1) ? 1'b1 : take; + assign BRANCH_TAKEN = pc_mux_sel_en & pc_mux_sel; + + always @(*) + begin + case (FUNCT3) + 3'b000: take = eq; + 3'b001: take = ne; + 3'b100: take = lt; + 3'b101: take = ge; + 3'b110: take = ltu; + 3'b111: take = geu; + default: take = 1'b0; + endcase + end + +endmodule Index: steelcore/trunk/control_unit.v =================================================================== --- steelcore/trunk/control_unit.v (nonexistent) +++ steelcore/trunk/control_unit.v (revision 11) @@ -0,0 +1,162 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 25.04.2020 14:49:16 +// Module Name: control_unit +// Project Name: Steel Core +// Description: Decodes the instruction and generates control signals +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module control_unit( + + input wire [6:0] OPCODE, + input wire FUNCT7_5, + input wire [2:0] FUNCT3, + input wire [1:0] IADDER_OUT_1_TO_0, + input wire TRAP_TAKEN, + + output wire [3:0] ALU_OPCODE, + output wire MEM_WR_REQ, + output wire [1:0] LOAD_SIZE, + output wire LOAD_UNSIGNED, + output wire ALU_SRC, + output wire IADDER_SRC, + output wire CSR_WR_EN, + output wire RF_WR_EN, + output wire [2:0] WB_MUX_SEL, + output wire [2:0] IMM_TYPE, + output wire [2:0] CSR_OP, + output wire ILLEGAL_INSTR, + output wire MISALIGNED_LOAD, + output wire MISALIGNED_STORE + + ); + + wire is_branch; + wire is_jal; + wire is_jalr; + wire is_auipc; + wire is_lui; + wire is_load; + wire is_store; + wire is_system; + wire is_csr; + wire is_op; + wire is_op_imm; + wire is_misc_mem; + wire is_addi; + wire is_slti; + wire is_sltiu; + wire is_andi; + wire is_ori; + wire is_xori; + wire is_addiw; + wire is_implemented_instr; + wire mal_word; + wire mal_half; + wire misaligned; + + assign LOAD_SIZE[0] = FUNCT3[0]; + assign LOAD_SIZE[1] = FUNCT3[1]; + assign LOAD_UNSIGNED = FUNCT3[2]; + assign ALU_SRC = OPCODE[5]; + assign is_branch = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_jal = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & OPCODE[3] & OPCODE[2]; + assign is_jalr = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & OPCODE[2]; + assign is_auipc = ~OPCODE[6] & ~OPCODE[5] & OPCODE[4] & ~OPCODE[3] & OPCODE[2]; + assign is_lui = ~OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & OPCODE[2]; + assign is_op = ~OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_op_imm = ~OPCODE[6] & ~OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_addi = is_op_imm & ~FUNCT3[2] & ~FUNCT3[1] & ~FUNCT3[0]; + assign is_slti = is_op_imm & ~FUNCT3[2] & FUNCT3[1] & ~FUNCT3[0]; + assign is_sltiu = is_op_imm & ~FUNCT3[2] & FUNCT3[1] & FUNCT3[0]; + assign is_andi = is_op_imm & FUNCT3[2] & FUNCT3[1] & FUNCT3[0]; + assign is_ori = is_op_imm & FUNCT3[2] & FUNCT3[1] & ~FUNCT3[0]; + assign is_xori = is_op_imm & FUNCT3[2] & ~FUNCT3[1] & ~FUNCT3[0]; + assign is_load = ~OPCODE[6] & ~OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_store = ~OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_system = OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2]; + assign is_misc_mem = ~OPCODE[6] & ~OPCODE[5] & ~OPCODE[4] & OPCODE[3] & OPCODE[2]; + assign is_csr = is_system & (FUNCT3[2] | FUNCT3[1] | FUNCT3[0]); + assign IADDER_SRC = is_load | is_store | is_jalr; + assign RF_WR_EN = is_lui | is_auipc | is_jalr | is_jal | is_op | is_load | is_csr | is_op_imm; + assign CSR_WR_EN = is_csr; + assign ALU_OPCODE[2:0] = FUNCT3; + assign ALU_OPCODE[3] = FUNCT7_5 & ~(is_addi | is_slti | is_sltiu | is_andi | is_ori | is_xori); + assign WB_MUX_SEL[0] = is_load | is_auipc | is_jal | is_jalr; + assign WB_MUX_SEL[1] = is_lui | is_auipc; + assign WB_MUX_SEL[2] = is_csr | is_jal | is_jalr; + assign IMM_TYPE[0] = is_op_imm | is_load | is_jalr | is_branch | is_jal; + assign IMM_TYPE[1] = is_store | is_branch | is_csr; + assign IMM_TYPE[2] = is_lui | is_auipc | is_jal | is_csr; + assign CSR_OP = FUNCT3; + assign is_implemented_instr = is_op | is_op_imm | is_branch | is_jal | is_jalr | is_auipc | is_lui | is_system | is_misc_mem | is_load | is_store; + assign ILLEGAL_INSTR = ~OPCODE[1] | ~OPCODE[0] | ~is_implemented_instr; + assign mal_word = FUNCT3[1] & ~FUNCT3[0] & (IADDER_OUT_1_TO_0[1] | IADDER_OUT_1_TO_0[0]); + assign mal_half = ~FUNCT3[1] & FUNCT3[0] & IADDER_OUT_1_TO_0[0]; + assign misaligned = mal_word | mal_half; + assign MISALIGNED_STORE = is_store & misaligned; + assign MISALIGNED_LOAD = is_load & misaligned; + assign MEM_WR_REQ = is_store & ~misaligned & ~TRAP_TAKEN; + + +endmodule Index: steelcore/trunk/csr_file.v =================================================================== --- steelcore/trunk/csr_file.v (nonexistent) +++ steelcore/trunk/csr_file.v (revision 11) @@ -0,0 +1,397 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 23:33:34 +// Module Name: csr_file +// Project Name: Steel Core +// Description: RISC-V Steel Core CSR Register File +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module csr_file( + + input wire CLK, + input wire RESET, + + input wire WR_EN, + input wire [11:0] CSR_ADDR, + input wire [2:0] CSR_OP, + input wire [4:0] CSR_UIMM, + input wire [31:0] CSR_DATA_IN, + output reg [31:0] CSR_DATA_OUT, + + // from pipeline stage 1 + input wire [31:0] PC, + + // interface with CLIC + input wire E_IRQ, + input wire T_IRQ, + input wire S_IRQ, + + // interface with Machine Control Module + input wire I_OR_E, + input wire SET_CAUSE, + input wire [3:0] CAUSE_IN, + input wire SET_EPC, + input wire INSTRET_INC, + input wire MIE_CLEAR, + input wire MIE_SET, + output reg MIE, + output wire MEIE_OUT, + output wire MTIE_OUT, + output wire MSIE_OUT, + output wire MEIP_OUT, + output wire MTIP_OUT, + output wire MSIP_OUT, + + // platform real time CLK value + input wire [63:0] REAL_TIME, + + // these two outputs are connected to the PC MUX + output wire [31:0] EPC_OUT, + output wire [31:0] TRAP_ADDRESS + + ); + + // Machine trap setup + wire [31:0] mstatus; // machine status register + wire [31:0] misa; // machine ISA register + wire [31:0] mie_reg; // machine interrupt enable register + wire [31:0] mtvec; + wire [1:0] mxl; // machine XLEN + wire [25:0] mextensions; // ISA extensions + reg [1:0] mtvec_mode; // machine trap mode + reg [29:0] mtvec_base; // machine trap base address + reg mpie; // mach. prior interrupt enable + reg meie; // mach. external interrupt enable + reg mtie; // mach. timer interrupt enable + reg msie; // mach. software interrupt enable + + // Machine trap handling + reg [31:0] mscratch; // machine scratch register + reg [31:0] mepc; // machine exception program counter + reg [31:0] mtval; // machine trap value register + wire [31:0] mcause; // machine trap cause register + wire [31:0] mip_reg; // machine interrupt pending register + reg int_or_exc; // interrupt or exception signal + reg [3:0] cause; // interrupt cause + reg [26:0] cause_rem; // remaining bits of mcause register + reg meip; // mach. external interrupt pending + reg mtip; // mach. timer interrupt pending + reg msip; // mach. software interrupt pending + + // Machine counters + reg [63:0] mcycle; + reg [63:0] mtime; + reg [63:0] minstret; + + // Machine counters setup + wire [31:0] mcountinhibit; + reg mcountinhibit_cy; + reg mcountinhibit_ir; + + // CSR operation control + // ---------------------------------------------------------------------------- + + reg [31:0] data_wr; + wire [31:0] pre_data; + + assign pre_data = CSR_OP[2] == 1'b1 ? {27'b0, CSR_UIMM} : CSR_DATA_IN; + + always @* + begin + case(CSR_OP[1:0]) + `CSR_RW: data_wr <= pre_data; + `CSR_RS: data_wr <= CSR_DATA_OUT | pre_data; + `CSR_RC: data_wr <= CSR_DATA_OUT & ~pre_data; + `CSR_NOP: data_wr <= CSR_DATA_OUT; + endcase + end + + always @* + begin + case(CSR_ADDR) + `CYCLE: CSR_DATA_OUT = mcycle[31:0]; + `CYCLEH: CSR_DATA_OUT = mcycle[63:32]; + `TIME: CSR_DATA_OUT = mtime[31:0]; + `TIMEH: CSR_DATA_OUT = mtime[63:32]; + `INSTRET: CSR_DATA_OUT = minstret[31:0]; + `INSTRETH: CSR_DATA_OUT = minstret[63:32]; + `MSTATUS: CSR_DATA_OUT = mstatus; + `MISA: CSR_DATA_OUT = misa; + `MIE: CSR_DATA_OUT = mie_reg; + `MTVEC: CSR_DATA_OUT = mtvec; + `MSCRATCH: CSR_DATA_OUT = mscratch; + `MEPC: CSR_DATA_OUT = mepc; + `MCAUSE: CSR_DATA_OUT = mcause; + `MTVAL: CSR_DATA_OUT = mtval; + `MIP: CSR_DATA_OUT = mip_reg; + `MCYCLE: CSR_DATA_OUT = mcycle[31:0]; + `MCYCLEH: CSR_DATA_OUT = mcycle[63:32]; + `MINSTRET: CSR_DATA_OUT = minstret[31:0]; + `MINSTRETH: CSR_DATA_OUT = minstret[63:32]; + `MCOUNTINHIBIT: CSR_DATA_OUT = mcountinhibit; + default: CSR_DATA_OUT = 32'b0; + endcase + end + + // MSTATUS register + // MPP + assign mstatus = {19'b0, 2'b11, 3'b0, mpie, 3'b0 , MIE, 3'b0}; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + MIE <= 1'b0; + mpie <= 1'b1; + end + else if(CSR_ADDR == `MSTATUS && WR_EN) + begin + MIE <= data_wr[3]; + mpie <= data_wr[7]; + end + else if(MIE_CLEAR == 1'b1) + begin + mpie <= MIE; + MIE <= 1'b0; + end + else if(MIE_SET == 1'b1) + begin + MIE <= mpie; + mpie <= 1'b1; + end + end + + // MISA register + assign mxl = 2'b01; + assign mextensions = 26'b00000000000000000100000000; + assign misa = {mxl, 4'b0, mextensions}; + + // MIE register + assign mie_reg = {20'b0, meie, 3'b0, mtie, 3'b0, msie, 3'b0}; + assign MEIE_OUT = meie; + assign MTIE_OUT = mtie; + assign MSIE_OUT = msie; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + meie <= 1'b0; + mtie <= 1'b0; + msie <= 1'b0; + end + else if(CSR_ADDR == `MIE && WR_EN) + begin + meie <= data_wr[11]; + mtie <= data_wr[7]; + msie <= data_wr[3]; + end + end + + // MTVEC register + assign mtvec = {mtvec_base, mtvec_mode}; + wire [31:0] trap_mux_out; + wire [31:0] vec_mux_out; + wire [31:0] base_offset; + assign base_offset = cause << 2; + assign trap_mux_out = int_or_exc ? vec_mux_out : {mtvec_base, 2'b00}; + assign vec_mux_out = mtvec[0] ? {mtvec_base, 2'b00} + base_offset : {mtvec_base, 2'b00}; + assign TRAP_ADDRESS = trap_mux_out; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + mtvec_mode <= `MTVEC_MODE_RESET; + mtvec_base <= `MTVEC_BASE_RESET; + end + else if(CSR_ADDR == `MTVEC && WR_EN) + begin + mtvec_mode <= data_wr[1:0]; + mtvec_base <= data_wr[31:2]; + end + end + + // MSCRATCH register + always @(posedge CLK or posedge RESET) + begin + if(RESET) mscratch <= `MSCRATCH_RESET; + else if(CSR_ADDR == `MSCRATCH && WR_EN) mscratch <= data_wr; + end + + // MEPC register + assign EPC_OUT = mepc; + always @(posedge CLK or posedge RESET) + begin + if(RESET) mepc <= `MEPC_RESET; + else if(SET_EPC) mepc <= PC; + else if(CSR_ADDR == `MEPC && WR_EN) mepc <= {data_wr[31:2], 2'b00}; + end + + // MCAUSE register + assign mcause = {int_or_exc, cause_rem, cause}; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + cause <= 4'b0000; + cause_rem <= 27'b0; + int_or_exc <= 1'b0; + end + else if(SET_CAUSE) + begin + cause <= CAUSE_IN; + cause_rem <= 27'b0; + int_or_exc <= I_OR_E; + end + else if(CSR_ADDR == `MCAUSE && WR_EN) + begin + cause <= data_wr[3:0]; + cause_rem <= data_wr[30:4]; + int_or_exc <= data_wr[31]; + + end + end + + // MIP register + assign mip_reg = {20'b0, meip, 3'b0, mtip, 3'b0, msip, 3'b0}; + assign MEIP_OUT = meip; + assign MTIP_OUT = mtip; + assign MSIP_OUT = msip; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + meip <= 1'b0; + mtip <= 1'b0; + msip <= 1'b0; + end + else + begin + meip <= E_IRQ; + mtip <= T_IRQ; + msip <= S_IRQ; + end + end + + // MTVAL register + always @(posedge CLK or posedge RESET) + begin + if(RESET) mtval <= 32'b0; + else if(SET_CAUSE) mtval <= 32'b0; + else if(CSR_ADDR == `MTVAL && WR_EN) mtval <= data_wr; + end + + // MCOUNTINHIBIT register + assign mcountinhibit = {29'b0, mcountinhibit_ir, 1'b0, mcountinhibit_cy}; + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + mcountinhibit_cy <= `MCOUNTINHIBIT_CY_RESET; + mcountinhibit_ir <= `MCOUNTINHIBIT_IR_RESET; + end + else if(CSR_ADDR == `MCOUNTINHIBIT && WR_EN) + begin + mcountinhibit_cy <= data_wr[2]; + mcountinhibit_ir <= data_wr[0]; + end + end + + // Counters + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + mcycle <= {`MCYCLEH_RESET, `MCYCLE_RESET}; + minstret <= {`MINSTRETH_RESET, `MINSTRET_RESET}; + mtime <= {`TIMEH_RESET, `TIME_RESET}; + end + else + begin + mtime <= REAL_TIME; + if(CSR_ADDR == `MCYCLE && WR_EN) + begin + mcycle[31:0] <= data_wr; + end + else if(CSR_ADDR == `MCYCLEH && WR_EN) + begin + mcycle[63:32] <= data_wr; + end + else + begin + if(mcountinhibit_cy == 1'b0) mcycle <= mcycle + 1; + end + if(CSR_ADDR == `MINSTRET && WR_EN) + begin + minstret[31:0] <= data_wr; + end + else if(CSR_ADDR == `MINSTRETH && WR_EN) + begin + minstret[63:32] <= data_wr; + end + else + begin + if(mcountinhibit_ir == 1'b0) minstret <= minstret + INSTRET_INC; + end + end + end + +endmodule Index: steelcore/trunk/globals.vh =================================================================== --- steelcore/trunk/globals.vh (nonexistent) +++ steelcore/trunk/globals.vh (revision 11) @@ -0,0 +1,281 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 30.03.2020 17:28:42 +// Module Name: - +// Project Name: STEM +// Description: RISC-V STEM Global Definitions +// +// Dependencies: - +// +// Revision: +// Revision 5.01 - Refactoring #5 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`ifndef GLOBALS_H +`define GLOBALS_H + +// ------------------------------------------------------------------------------- +// SETUP +// ------------------------------------------------------------------------------- + +// Boot address +`define BOOT_ADDRESS 32'h00000000 + +// CSR registers reset values +`define MCYCLE_RESET 32'h00000000 +`define TIME_RESET 32'h00000000 +`define MINSTRET_RESET 32'h00000000 +`define MCYCLEH_RESET 32'h00000000 +`define TIMEH_RESET 32'h00000000 +`define MINSTRETH_RESET 32'h00000000 +`define MTVEC_BASE_RESET 30'b00000000_00000000_00000000_000000 +`define MTVEC_MODE_RESET 2'b00 +`define MSCRATCH_RESET 32'h00000000 +`define MEPC_RESET 32'h00000000 +`define MCOUNTINHIBIT_CY_RESET 1'b0 +`define MCOUNTINHIBIT_IR_RESET 1'b0 + + +// ------------------------------------------------------------------------------- +// WARNING: THE VALUES BELOW MUST NOT BE MODIFIED +// ------------------------------------------------------------------------------- + +// Implemented instructions opcodes + +`define NOP_INSTR 32'b000000000000_00000_000_00000_0010011 +`define OPCODE_OP 5'b01100 +`define OPCODE_OP_IMM 5'b00100 +`define OPCODE_LOAD 5'b00000 +`define OPCODE_STORE 5'b01000 +`define OPCODE_BRANCH 5'b11000 +`define OPCODE_JAL 5'b11011 +`define OPCODE_JALR 5'b11001 +`define OPCODE_LUI 5'b01101 +`define OPCODE_AUIPC 5'b00101 +`define OPCODE_MISC_MEM 5'b00011 +`define OPCODE_SYSTEM 5'b11100 + +// funct7 and funct3 for logic and arithmetic instructions + +`define FUNCT7_SUB 7'b0100000 +`define FUNCT7_SRA 7'b0100000 +`define FUNCT7_ADD 7'b0000000 +`define FUNCT7_SLT 7'b0000000 +`define FUNCT7_SLTU 7'b0000000 +`define FUNCT7_AND 7'b0000000 +`define FUNCT7_OR 7'b0000000 +`define FUNCT7_XOR 7'b0000000 +`define FUNCT7_SLL 7'b0000000 +`define FUNCT7_SRL 7'b0000000 +`define FUNCT7_SRAI 7'b0100000 +`define FUNCT7_ADDI 7'bxxxxxxx +`define FUNCT7_SLTI 7'bxxxxxxx +`define FUNCT7_SLTIU 7'bxxxxxxx +`define FUNCT7_ANDI 7'bxxxxxxx +`define FUNCT7_ORI 7'bxxxxxxx +`define FUNCT7_XORI 7'bxxxxxxx +`define FUNCT7_SLLI 7'b0000000 +`define FUNCT7_SRLI 7'b0000000 + +`define FUNCT3_ADD 3'b000 +`define FUNCT3_SUB 3'b000 +`define FUNCT3_SLT 3'b010 +`define FUNCT3_SLTU 3'b011 +`define FUNCT3_AND 3'b111 +`define FUNCT3_OR 3'b110 +`define FUNCT3_XOR 3'b100 +`define FUNCT3_SLL 3'b001 +`define FUNCT3_SRL 3'b101 +`define FUNCT3_SRA 3'b101 + +// ALU operations encoding + +`define ALU_ADD 4'b0000 +`define ALU_SUB 4'b1000 +`define ALU_SLT 4'b0010 +`define ALU_SLTU 4'b0011 +`define ALU_AND 4'b0111 +`define ALU_OR 4'b0110 +`define ALU_XOR 4'b0100 +`define ALU_SLL 4'b0001 +`define ALU_SRL 4'b0101 +`define ALU_SRA 4'b1101 + +// funct7 and funct3 for other instructions + +`define FUNCT7_ECALL 7'b0000000 +`define FUNCT7_EBREAK 7'b0000000 +`define FUNCT7_MRET 7'B0011000 + +`define FUNCT3_CSRRW 3'b001 +`define FUNCT3_CSRRS 3'b010 +`define FUNCT3_CSRRC 3'b011 +`define FUNCT3_CSRRWI 3'b101 +`define FUNCT3_CSRRSI 3'b110 +`define FUNCT3_CSRRCI 3'b111 + +`define FUNCT3_BEQ 3'b000 +`define FUNCT3_BNE 3'b001 +`define FUNCT3_BLT 3'b100 +`define FUNCT3_BGE 3'b101 +`define FUNCT3_BLTU 3'b110 +`define FUNCT3_BGEU 3'b111 + +`define FUNCT3_ECALL 3'b000 +`define FUNCT3_EBREAK 3'b000 +`define FUNCT3_MRET 3'b000 +`define FUNCT3_WFI 3'b000 + +`define FUNCT3_BYTE 3'b000 +`define FUNCT3_HALF 3'b001 +`define FUNCT3_WORD 3'b010 +`define FUNCT3_BYTE_U 3'b100 +`define FUNCT3_HALF_U 3'b101 + +// rd, rs1 and rs2 values for SYSTEM instructions + +`define RS1_ECALL 5'b00000 +`define RS1_EBREAK 5'b00000 +`define RS1_MRET 5'b00000 +`define RS1_WFI 5'b00000 + +`define RS2_ECALL 5'b00000 +`define RS2_EBREAK 5'b00001 +`define RS2_MRET 5'b00010 +`define RS2_WFI 5'b00101 + +`define RD_ECALL 5'b00000 +`define RD_EBREAK 5'b00000 +`define RD_MRET 5'b00000 +`define RD_WFI 5'b00000 + +// writeback selection +`define WB_ALU 3'b000 +`define WB_LU 3'b001 +`define WB_IMM 3'b010 +`define WB_IADDER_OUT 3'b011 +`define WB_CSR 3'b100 +`define WB_PC_PLUS 3'b101 + +// immediate format selection + +`define R_TYPE 3'b000 +`define I_TYPE 3'b001 +`define S_TYPE 3'b010 +`define B_TYPE 3'b011 +`define U_TYPE 3'b100 +`define J_TYPE 3'b101 +`define CSR_TYPE 3'b110 + +// PC MUX selection + +`define PC_BOOT 2'b00 +`define PC_EPC 2'b01 +`define PC_TRAP 2'b10 +`define PC_NEXT 2'b11 + +// mask for byte-writes + +`define WR_MASK_BYTE 4'b0001 +`define WR_MASK_HALF 4'b0011 +`define WR_MASK_WORD 4'b1111 + +// load unit control encoding + +`define LOAD_BYTE 2'b00 +`define LOAD_HALF 2'b01 +`define LOAD_WORD 2'b10 + +// CSR File operation encoding + +`define CSR_NOP 2'b00 +`define CSR_RW 2'b01 +`define CSR_RS 2'b10 +`define CSR_RC 2'b11 + +// CSR ADDRESSES ---------------------------- + +// Performance Counters +`define CYCLE 12'hC00 +`define TIME 12'hC01 +`define INSTRET 12'hC02 +`define CYCLEH 12'hC80 +`define TIMEH 12'hC81 +`define INSTRETH 12'hC82 + +// Machine Trap Setup +`define MSTATUS 12'h300 +`define MISA 12'h301 +`define MIE 12'h304 +`define MTVEC 12'h305 + +// Machine Trap Handling +`define MSCRATCH 12'h340 +`define MEPC 12'h341 +`define MCAUSE 12'h342 +`define MTVAL 12'h343 +`define MIP 12'h344 + +// Machine Counter / Timers +`define MCYCLE 12'hB00 +`define MINSTRET 12'hB02 +`define MCYCLEH 12'hB80 +`define MINSTRETH 12'hB82 + +// Machine Counter Setup +`define MCOUNTINHIBIT 12'h320 + +`endif Index: steelcore/trunk/imm_generator.v =================================================================== --- steelcore/trunk/imm_generator.v (nonexistent) +++ steelcore/trunk/imm_generator.v (revision 11) @@ -0,0 +1,105 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 22:01:22 +// Module Name: imm_generator +// Project Name: Steel Core +// Description: Generates the immediate according with the instruction +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module imm_generator( + + input wire [31:7] INSTR, + input wire [2:0] IMM_TYPE, + output reg [31:0] IMM + + ); + + wire [31:0] i_type; + wire [31:0] s_type; + wire [31:0] b_type; + wire [31:0] u_type; + wire [31:0] j_type; + wire [31:0] csr_type; + + assign i_type = { {20{INSTR[31]}}, INSTR[31:20] }; + assign s_type = { {20{INSTR[31]}}, INSTR[31:25], INSTR[11:7] }; + assign b_type = { {19{INSTR[31]}}, INSTR[31], INSTR[7], INSTR[30:25], INSTR[11:8], 1'b0 }; + assign u_type = { INSTR[31:12], 12'h000 }; + assign j_type = { {11{INSTR[31]}}, INSTR[31], INSTR[19:12], INSTR[20], INSTR[30:21], 1'b0 }; + assign csr_type = { 27'b0, INSTR[19:15] }; + + always @(*) + begin + case (IMM_TYPE) + 3'b000: IMM = i_type; + `I_TYPE: IMM = i_type; + `S_TYPE: IMM = s_type; + `B_TYPE: IMM = b_type; + `U_TYPE: IMM = u_type; + `J_TYPE: IMM = j_type; + `CSR_TYPE: IMM = csr_type; + 3'b111: IMM = i_type; + endcase + end + +endmodule Index: steelcore/trunk/integer_file.v =================================================================== --- steelcore/trunk/integer_file.v (nonexistent) +++ steelcore/trunk/integer_file.v (revision 11) @@ -0,0 +1,137 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 02.04.2020 23:23:16 +// Module Name: register_file +// Project Name: Steel Core +// Description: RISC-V Steel Core 32-bit Integer Register File +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module integer_file( + + input wire CLK, + input wire RESET, + + // connections with pipeline stage 2 + input wire [4:0] RS_1_ADDR, + input wire [4:0] RS_2_ADDR, + output wire [31:0] RS_1, + output wire [31:0] RS_2, + + // connections with pipeline stage 3 + input wire [4:0] RD_ADDR, + input wire WR_EN, + input wire [31:0] RD + + ); + + wire [31:0] data_out [31:0]; + wire [31:0] rs1_wire; + wire [31:0] rs2_wire; + wire [31:1] enable; + wire fwd_op1_enable; + wire fwd_op2_enable; + wire fwd_op1_zero; + wire fwd_op2_zero; + wire [31:0] reg_en; + reg [31:0] rs1_reg; + reg [31:0] rs2_reg; + wire rs1_addr_is_x0; + wire rs2_addr_is_x0; + reg [31:0] Q [31:1]; + + genvar i; + generate + for(i = 1; i < 32; i=i+1) + begin:regn + and and_en(enable[i], reg_en[i], WR_EN); + always @(posedge CLK or posedge RESET) + begin + if(RESET) Q[i] <= 32'h00000000; + else if(enable[i]) Q[i] <= RD; + end + assign data_out[i] = Q[i]; + end + endgenerate + + assign data_out[0] = 32'h00000000; + + always @(*) + begin + rs1_reg = data_out[RS_1_ADDR]; + rs2_reg = data_out[RS_2_ADDR]; + end + + assign reg_en = 32'h00000001 << RD_ADDR; + + assign rs1_addr_is_x0 = RS_1_ADDR == 5'b00000; + assign rs2_addr_is_x0 = RS_2_ADDR == 5'b00000; + assign fwd_op1_enable = RS_1_ADDR == RD_ADDR ? 1'b1 : 1'b0; + assign fwd_op2_enable = RS_2_ADDR == RD_ADDR ? 1'b1 : 1'b0; + assign fwd_op1_zero = rs1_addr_is_x0 == 1'b1 ? 1'b1 : 1'b0; + assign fwd_op2_zero = rs2_addr_is_x0 == 1'b1 ? 1'b1 : 1'b0; + assign rs1_wire = fwd_op1_enable == 1'b1 ? RD : rs1_reg; + assign rs2_wire = fwd_op2_enable == 1'b1 ? RD : rs2_reg; + assign RS_1 = fwd_op1_zero == 1'b1 ? 32'h00000000 : rs1_wire; + assign RS_2 = fwd_op2_zero == 1'b1 ? 32'h00000000 : rs2_wire; + +endmodule Index: steelcore/trunk/load_unit.v =================================================================== --- steelcore/trunk/load_unit.v (nonexistent) +++ steelcore/trunk/load_unit.v (revision 11) @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 20:30:54 +// Module Name: load_unit +// Project Name: Steel Core +// Description: Sign extends the data read from memory +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module load_unit( + + input wire [1:0] LOAD_SIZE, + input wire LOAD_UNSIGNED, + input wire [31:0] DATA_IN, + input wire [1:0] IADDER_OUT_1_TO_0, + output reg [31:0] OUTPUT + + ); + + reg [7:0] byte; + reg [15:0] half; + wire [23:0] byte_ext; + wire [15:0] half_ext; + + always @* + begin + + case(LOAD_SIZE) + + 2'b00: OUTPUT = {byte_ext, byte}; + 2'b01: OUTPUT = {half_ext, half}; + 2'b10: OUTPUT = DATA_IN; + 2'b11: OUTPUT = DATA_IN; + + endcase + + end + + always @* + begin + + case(IADDER_OUT_1_TO_0) + + 2'b00: byte = DATA_IN[7:0]; + 2'b01: byte = DATA_IN[15:8]; + 2'b10: byte = DATA_IN[23:16]; + 2'b11: byte = DATA_IN[31:24]; + + endcase + + end + + always @* + begin + + case(IADDER_OUT_1_TO_0[1]) + + 1'b0: half = DATA_IN[15:0]; + 1'b1: half = DATA_IN[31:16]; + + endcase + + end + + assign byte_ext = LOAD_UNSIGNED == 1'b1 ? 24'b0 : {24{byte[7]}}; + assign half_ext = LOAD_UNSIGNED == 1'b1 ? 16'b0 : {16{half[15]}}; + +endmodule Index: steelcore/trunk/machine_control.v =================================================================== --- steelcore/trunk/machine_control.v (nonexistent) +++ steelcore/trunk/machine_control.v (revision 11) @@ -0,0 +1,320 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 26.04.2020 23:18:08 +// Module Name: machine_control +// Project Name: Steel Core +// Description: Controls the M-mode operation +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module machine_control( + + input wire CLK, + input wire RESET, + + // from control unit + input wire ILLEGAL_INSTR, + input wire MISALIGNED_LOAD, + input wire MISALIGNED_STORE, + + // from pipeline stage 1 + input wire MISALIGNED_INSTR, + + // from instruction + input wire [6:2] OPCODE_6_TO_2, + input wire [2:0] FUNCT3, + input wire [6:0] FUNCT7, + input wire [4:0] RS1_ADDR, + input wire [4:0] RS2_ADDR, + input wire [4:0] RD_ADDR, + + // from interrupt controller + input wire E_IRQ, + input wire T_IRQ, + input wire S_IRQ, + + // from CSR file + input wire MIE, + input wire MEIE, + input wire MTIE, + input wire MSIE, + input wire MEIP, + input wire MTIP, + input wire MSIP, + + // to CSR file + output reg I_OR_E, + output reg SET_EPC, + output reg SET_CAUSE, + output reg [3:0] CAUSE, + output reg INSTRET_INC, + output reg MIE_CLEAR, + output reg MIE_SET, + + // to PC MUX + output reg [1:0] PC_SRC, + + // to pipeline stage 2 register + output reg FLUSH, + + // to Control Unit + output wire TRAP_TAKEN + + ); + + // state registers + reg [3:0] curr_state; + reg [3:0] next_state; + + // machine states + parameter STATE_RESET = 2'b00; + parameter STATE_OPERATING = 2'b01; + parameter STATE_TRAP_TAKEN = 2'b10; + parameter STATE_TRAP_RETURN = 2'b11; + + // internal control signals + wire exception; + wire ip; + wire eip; + wire tip; + wire sip; + wire is_system; + wire RS1_ADDR_zero; + wire RS2_ADDR_zero; + wire rd_zero; + wire RS2_ADDR_mret; + wire RS2_ADDR_ebreak; + wire FUNCT3_zero; + wire FUNCT7_zero; + wire FUNCT7_mret; + wire csr; + wire mret; + wire ecall; + wire ebreak; + reg pre_instret_inc; + + // COMBINATIONAL LOGIC ------------------------------------------- + + assign is_system = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & ~OPCODE_6_TO_2[2]; + assign FUNCT3_zero = ~(FUNCT3[2] | FUNCT3[1] | FUNCT3[0]); + assign FUNCT7_zero = ~(FUNCT7[6] | FUNCT7[5] | FUNCT7[4] | FUNCT7[3] | FUNCT7[2] | FUNCT7[1] | FUNCT7[0]); + assign FUNCT7_wfi = ~FUNCT7[6] & ~FUNCT7[5] & ~FUNCT7[4] & FUNCT7[3] & ~FUNCT7[2] & ~FUNCT7[1] & ~FUNCT7[0]; + assign FUNCT7_mret = ~FUNCT7[6] & ~FUNCT7[5] & FUNCT7[4] & FUNCT7[3] & ~FUNCT7[2] & ~FUNCT7[1] & ~FUNCT7[0]; + assign RS1_ADDR_zero = ~(RS1_ADDR[4] | RS1_ADDR[3] | RS1_ADDR[2] | RS1_ADDR[1] | RS1_ADDR[0]); + assign RS2_ADDR_zero = ~(RS2_ADDR[4] | RS2_ADDR[3] | RS2_ADDR[2] | RS2_ADDR[1] | RS2_ADDR[0]); + assign rd_zero = ~(RD_ADDR[4] | RD_ADDR[3] | RD_ADDR[2] | RD_ADDR[1] | RD_ADDR[0]); + assign RS2_ADDR_wfi = ~RS2_ADDR[4] & ~RS2_ADDR[3] & RS2_ADDR[2] & ~RS2_ADDR[1] & RS2_ADDR[0]; + assign RS2_ADDR_mret = ~RS2_ADDR[4] & ~RS2_ADDR[3] & ~RS2_ADDR[2] & RS2_ADDR[1] & ~RS2_ADDR[0]; + assign RS2_ADDR_ebreak = ~RS2_ADDR[4] & ~RS2_ADDR[3] & ~RS2_ADDR[2] & ~RS2_ADDR[1] & RS2_ADDR[0]; + assign mret = is_system & FUNCT7_mret & RS2_ADDR_mret & RS1_ADDR_zero & FUNCT3_zero & rd_zero; + assign ecall = is_system & FUNCT7_zero & RS2_ADDR_zero & RS1_ADDR_zero & FUNCT3_zero & rd_zero; + assign ebreak = is_system & FUNCT7_zero & RS2_ADDR_ebreak & RS1_ADDR_zero & FUNCT3_zero & rd_zero; + + assign eip = MEIE & (E_IRQ | MEIP); + assign tip = MTIE & (T_IRQ | MTIP); + assign sip = MSIE & (S_IRQ | MSIP); + assign ip = eip | tip | sip; + assign exception = ILLEGAL_INSTR | MISALIGNED_INSTR | MISALIGNED_LOAD | MISALIGNED_STORE; + assign TRAP_TAKEN = (MIE & ip) | exception | ecall | ebreak; + + always @* + begin + case(curr_state) + STATE_RESET: + next_state = STATE_OPERATING; + STATE_OPERATING: + if(TRAP_TAKEN) next_state = STATE_TRAP_TAKEN; + else if(mret) next_state = STATE_TRAP_RETURN; + else next_state = STATE_OPERATING; + STATE_TRAP_TAKEN: + next_state = STATE_OPERATING; + STATE_TRAP_RETURN: + next_state = STATE_OPERATING; + default: + next_state = STATE_OPERATING; + endcase + end + + // output generation + always @* + begin + case(curr_state) + STATE_RESET: + begin + PC_SRC = `PC_BOOT; + FLUSH = 1'b1; + INSTRET_INC = 1'b0; + SET_EPC = 1'b0; + SET_CAUSE = 1'b0; + MIE_CLEAR = 1'b0; + MIE_SET = 1'b0; + end + STATE_OPERATING: + begin + PC_SRC = `PC_NEXT; + FLUSH = 1'b0; + INSTRET_INC = 1'b1; + SET_EPC = 1'b0; + SET_CAUSE = 1'b0; + MIE_CLEAR = 1'b0; + MIE_SET = 1'b0; + end + STATE_TRAP_TAKEN: + begin + PC_SRC = `PC_TRAP; + FLUSH = 1'b1; + INSTRET_INC = 1'b0; + SET_EPC = 1'b1; + SET_CAUSE = 1'b1; + MIE_CLEAR = 1'b1; + MIE_SET = 1'b0; + end + STATE_TRAP_RETURN: + begin + PC_SRC = `PC_EPC; + FLUSH = 1'b1; + INSTRET_INC = 1'b0; + SET_EPC = 1'b0; + SET_CAUSE = 1'b0; + MIE_CLEAR = 1'b0; + MIE_SET = 1'b1; + end + default: + begin + PC_SRC = `PC_NEXT; + FLUSH = 1'b0; + INSTRET_INC = 1'b1; + SET_EPC = 1'b0; + SET_CAUSE = 1'b0; + MIE_CLEAR = 1'b0; + MIE_SET = 1'b0; + end + endcase + + end + + // SEQUENTIAL LOGIC ------------------------------------------- + + always @(posedge CLK or posedge RESET) + begin + if(RESET) curr_state <= STATE_RESET; + else curr_state <= next_state; + end + + always @(posedge CLK or posedge RESET) + begin + if(RESET) + begin + CAUSE <= 4'b0; + I_OR_E <= 1'b0; + end + else if(curr_state == STATE_OPERATING) + begin + if(MIE & eip) + begin + CAUSE <= 4'b1011; // M-mode external interrupt + I_OR_E <= 1'b1; + end + else if(MIE & sip) + begin + CAUSE <= 4'b0011; // M-mode software interrupt + I_OR_E <= 1'b1; + end + else if(MIE & tip) + begin + CAUSE <= 4'b0111; // M-mode timer interrupt + I_OR_E <= 1'b1; + end + else if(ILLEGAL_INSTR) + begin + CAUSE <= 4'b0010; // Illegal instruction + I_OR_E <= 1'b0; + end + else if(MISALIGNED_INSTR) + begin + CAUSE <= 4'b0000; // Instruction address misaligned + I_OR_E <= 1'b0; + end + else if(ecall) + begin + CAUSE <= 4'b1011; // Environment call from M-mode + I_OR_E <= 1'b0; + end + else if(ebreak) + begin + CAUSE <= 4'b0011; // Breakpoint + I_OR_E <= 1'b0; + end + else if(MISALIGNED_STORE) + begin + CAUSE <= 4'b0110; // Store address misaligned + I_OR_E <= 1'b0; + end + else if(MISALIGNED_LOAD) + begin + CAUSE <= 4'b0100; // Load address misaligned + I_OR_E <= 1'b0; + end + end + end + +endmodule Index: steelcore/trunk/steel_top.v =================================================================== --- steelcore/trunk/steel_top.v (nonexistent) +++ steelcore/trunk/steel_top.v (revision 11) @@ -0,0 +1,481 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 30.04.2020 02:39:50 +// Module Name: steel_top +// Project Name: Steel Core +// Description: RISC-V Steel Core top module +// +// Dependencies: globals.vh +// machine_control.v +// alu.v +// integer_file.v +// branch_unit.v +// control_unit.v +// csr_file.v +// imm_generator.v +// load_unit.v +// store_unit.v +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module steel_top( + + input wire CLK, + input wire RESET, + + // connection with Real Time Counter + input wire [63:0] REAL_TIME, + + // connections with Instruction Memory + output wire [31:0] I_ADDR, + input wire [31:0] INSTR, + + // connections with Data Memory + output wire [31:0] D_ADDR, + output wire [31:0] DATA_OUT, + output wire WR_REQ, + output wire [3:0] WR_MASK, + input wire [31:0] DATA_IN, + + //connections with Interrupt Controller + input wire E_IRQ, + input wire T_IRQ, + input wire S_IRQ + + ); + + // --------------------------------- + // Internal wires and registers + // --------------------------------- + + wire [4:0] RS1_ADDR; + wire [4:0] RS2_ADDR; + wire [4:0] RD_ADDR; + reg [4:0] RD_ADDR_reg; + wire [31:0] CSR_DATA; + wire [11:0] CSR_ADDR; + reg [11:0] CSR_ADDR_reg; + wire [31:0] RS1; + reg [31:0] RS1_reg; + wire [31:0] RS2; + reg [31:0] RS2_reg; + reg [31:0] PC; + wire [31:0] NEXT_PC; + wire [31:0] PC_PLUS_4; + reg [31:0] PC_PLUS_4_reg; + wire BRANCH_TAKEN; + wire [31:0] IADDER_OUT; + reg [31:0] IADDER_OUT_reg; + wire [31:0] EPC; + wire [31:0] TRAP_ADDRESS; + wire [1:0] PC_SRC; + wire [6:0] OPCODE; + wire [6:0] FUNCT7; + wire [2:0] FUNCT3; + wire [3:0] ALU_OPCODE; + reg [3:0] ALU_OPCODE_reg; + wire MEM_WR_REQ; + wire [3:0] MEM_WR_MASK; + wire [1:0] LOAD_SIZE; + reg [1:0] LOAD_SIZE_reg; + wire LOAD_UNSIGNED; + reg LOAD_UNSIGNED_reg; + wire ALU_SRC; + reg ALU_SRC_reg; + wire IADDER_SRC; + wire CSR_WR_EN; + reg CSR_WR_EN_reg; + wire RF_WR_EN; + reg RF_WR_EN_reg; + wire [2:0] WB_MUX_SEL; + reg [2:0] WB_MUX_SEL_reg; + wire [2:0] IMM_TYPE; + wire [2:0] CSR_OP; + reg [2:0] CSR_OP_reg; + wire ILLEGAL_INSTR; + wire MISALIGNED_LOAD; + wire MISALIGNED_STORE; + wire [31:0] IMM; + reg [31:0] IMM_reg; + wire I_OR_E; + wire SET_CAUSE; + wire [3:0] CAUSE_IN; + wire SET_EPC; + wire INSTRET_INC; + wire MIE_CLEAR; + wire MIE_SET; + wire MIE; + wire MEIE_OUT; + wire MTIE_OUT; + wire MSIE_OUT; + wire MEIP_OUT; + wire MTIP_OUT; + wire MSIP_OUT; + wire FLUSH; + wire [31:0] LU_OUTPUT; + wire [31:0] ALU_RESULT; + reg [31:0] WB_MUX_OUT; + wire RESET_OR_FLUSH; + wire [31:0] SU_DATA_OUT; + wire [31:0] SU_D_ADDR; + wire [3:0] SU_WR_MASK; + wire SU_WR_REQ; + wire TRAP_TAKEN; + + // --------------------------------- + // PIPELINE STAGE 1 + // --------------------------------- + + // PC MUX + + reg [31:0] PC_MUX_OUT; + always @* + begin + case (PC_SRC) + `PC_BOOT: PC_MUX_OUT = `BOOT_ADDRESS; + `PC_EPC: PC_MUX_OUT = EPC; + `PC_TRAP: PC_MUX_OUT = TRAP_ADDRESS; + `PC_NEXT: PC_MUX_OUT = NEXT_PC; + endcase + end + + // PC Adder and Multiplexer + assign PC_PLUS_4 = PC + 32'h00000004; + assign NEXT_PC = BRANCH_TAKEN ? {IADDER_OUT[31:1], 1'b0} : PC_PLUS_4; + + // Program Counter (PC) register + always @(posedge CLK or posedge RESET) + begin + if(RESET) PC <= `BOOT_ADDRESS; + else PC <= PC_MUX_OUT; + end + + // --------------------------------- + // PIPELINE STAGE 2 + // --------------------------------- + + wire [31:0] INSTR_mux; + assign INSTR_mux = FLUSH == 1'b1 ? 32'h00000013 : INSTR; + + assign OPCODE = INSTR_mux[6:0]; + assign FUNCT3 = INSTR_mux[14:12]; + assign FUNCT7 = INSTR_mux[31:25]; + + store_unit su( + + .FUNCT3(FUNCT3[1:0]), + .IADDER_OUT(IADDER_OUT), + .RS2(RS2), + .MEM_WR_REQ(MEM_WR_REQ), + + .DATA_OUT(SU_DATA_OUT), + .D_ADDR(SU_D_ADDR), + .WR_MASK(SU_WR_MASK), + .WR_REQ(SU_WR_REQ) + + ); + + control_unit ctrlunit( + + .OPCODE(OPCODE), + .FUNCT7_5(FUNCT7[5]), + .FUNCT3(FUNCT3), + .IADDER_OUT_1_TO_0(IADDER_OUT[1:0]), + .TRAP_TAKEN(TRAP_TAKEN), + + .ALU_OPCODE(ALU_OPCODE), + .MEM_WR_REQ(MEM_WR_REQ), + .LOAD_SIZE(LOAD_SIZE), + .LOAD_UNSIGNED(LOAD_UNSIGNED), + .ALU_SRC(ALU_SRC), + .IADDER_SRC(IADDER_SRC), + .CSR_WR_EN(CSR_WR_EN), + .RF_WR_EN(RF_WR_EN), + .WB_MUX_SEL(WB_MUX_SEL), + .IMM_TYPE(IMM_TYPE), + .CSR_OP(CSR_OP), + .ILLEGAL_INSTR(ILLEGAL_INSTR), + .MISALIGNED_LOAD(MISALIGNED_LOAD), + .MISALIGNED_STORE(MISALIGNED_STORE) + + ); + + imm_generator immgen( + + .INSTR(INSTR_mux[31:7]), + .IMM_TYPE(IMM_TYPE), + .IMM(IMM) + + ); + + // Immediate Adder + wire [31:0] iadder_mux_out; + assign iadder_mux_out = IADDER_SRC == 1'b1 ? RS1 : PC; + assign IADDER_OUT = iadder_mux_out + IMM; + + branch_unit bunit( + + .OPCODE_6_TO_2(OPCODE[6:2]), + .FUNCT3(FUNCT3), + .RS1(RS1), + .RS2(RS2), + .BRANCH_TAKEN(BRANCH_TAKEN) + + ); + + assign RS1_ADDR = INSTR_mux[19:15]; + assign RS2_ADDR = INSTR_mux[24:20]; + assign RD_ADDR = INSTR_mux[11:7]; + + integer_file irf( + + .CLK(CLK), + .RESET(RESET), + + .RS_1_ADDR(RS1_ADDR), + .RS_2_ADDR(RS2_ADDR), + .RS_1(RS1), + .RS_2(RS2), + + .RD_ADDR(RD_ADDR_reg), + .WR_EN(RF_WR_EN_reg), + .RD(WB_MUX_OUT) + + ); + + assign CSR_ADDR = INSTR_mux[31:20]; + + csr_file csrf( + + .CLK(CLK), + .RESET(RESET), + + .WR_EN(CSR_WR_EN_reg), + .CSR_ADDR(CSR_ADDR_reg), + .CSR_OP(CSR_OP_reg), + .CSR_UIMM(IMM_reg[4:0]), + .CSR_DATA_IN(RS1_reg), + .CSR_DATA_OUT(CSR_DATA), + + .PC(PC), + + .E_IRQ(E_IRQ), + .T_IRQ(T_IRQ), + .S_IRQ(S_IRQ), + + .I_OR_E(I_OR_E), + .SET_CAUSE(SET_CAUSE), + .CAUSE_IN(CAUSE_IN), + .SET_EPC(SET_EPC), + .INSTRET_INC(INSTRET_INC), + .MIE_CLEAR(MIE_CLEAR), + .MIE_SET(MIE_SET), + .MIE(MIE), + .MEIE_OUT(MEIE_OUT), + .MTIE_OUT(MTIE_OUT), + .MSIE_OUT(MSIE_OUT), + .MEIP_OUT(MEIP_OUT), + .MTIP_OUT(MTIP_OUT), + .MSIP_OUT(MSIP_OUT), + + .REAL_TIME(REAL_TIME), + + .EPC_OUT(EPC), + .TRAP_ADDRESS(TRAP_ADDRESS) + + ); + + machine_control mc( + + .CLK(CLK), + .RESET(RESET), + + .ILLEGAL_INSTR(ILLEGAL_INSTR), + .MISALIGNED_INSTR(BRANCH_TAKEN & NEXT_PC[1]), + .MISALIGNED_LOAD(MISALIGNED_LOAD), + .MISALIGNED_STORE(MISALIGNED_STORE), + + .OPCODE_6_TO_2(OPCODE[6:2]), + .FUNCT3(FUNCT3), + .FUNCT7(FUNCT7), + .RS1_ADDR(RS1_ADDR), + .RS2_ADDR(RS2_ADDR), + .RD_ADDR(RD_ADDR), + + .E_IRQ(E_IRQ), + .T_IRQ(T_IRQ), + .S_IRQ(S_IRQ), + + .I_OR_E(I_OR_E), + .SET_CAUSE(SET_CAUSE), + .CAUSE(CAUSE_IN), + .SET_EPC(SET_EPC), + .INSTRET_INC(INSTRET_INC), + .MIE_CLEAR(MIE_CLEAR), + .MIE_SET(MIE_SET), + .MIE(MIE), + .MEIE(MEIE_OUT), + .MTIE(MTIE_OUT), + .MSIE(MSIE_OUT), + .MEIP(MEIP_OUT), + .MTIP(MTIP_OUT), + .MSIP(MSIP_OUT), + + .PC_SRC(PC_SRC), + + .FLUSH(FLUSH), + + .TRAP_TAKEN(TRAP_TAKEN) + + ); + + assign RESET_OR_FLUSH = RESET | FLUSH; + + // Stages 1/2 interface registers + always @(posedge CLK or posedge RESET_OR_FLUSH) + begin + if(RESET_OR_FLUSH) + begin + RD_ADDR_reg <= 5'b00000; + CSR_ADDR_reg <= 12'b000000000000; + RS1_reg <= 32'h00000000; + RS2_reg <= 32'h00000000; + PC_PLUS_4_reg <= 32'h00000000; + IADDER_OUT_reg <= 32'h00000000; + ALU_OPCODE_reg <= 4'b0000; + LOAD_SIZE_reg <= 2'b00; + LOAD_UNSIGNED_reg <= 1'b0; + ALU_SRC_reg <= 1'b0; + CSR_WR_EN_reg <= 1'b0; + RF_WR_EN_reg <= 1'b0; + WB_MUX_SEL_reg <= `WB_ALU; + CSR_OP_reg <= 3'b000; + IMM_reg <= 32'h00000000; + end + else + begin + RD_ADDR_reg <= RD_ADDR; + CSR_ADDR_reg <= CSR_ADDR; + RS1_reg <= RS1; + RS2_reg <= RS2; + PC_PLUS_4_reg <= PC_PLUS_4; + IADDER_OUT_reg <= IADDER_OUT; + ALU_OPCODE_reg <= ALU_OPCODE; + LOAD_SIZE_reg <= LOAD_SIZE; + LOAD_UNSIGNED_reg <= LOAD_UNSIGNED; + ALU_SRC_reg <= ALU_SRC; + CSR_WR_EN_reg <= CSR_WR_EN; + RF_WR_EN_reg <= RF_WR_EN; + WB_MUX_SEL_reg <= WB_MUX_SEL; + CSR_OP_reg <= CSR_OP; + IMM_reg <= IMM; + end + end + + // --------------------------------- + // PIPELINE STAGE 3 + // --------------------------------- + + load_unit lu( + + .LOAD_SIZE(LOAD_SIZE_reg), + .LOAD_UNSIGNED(LOAD_UNSIGNED_reg), + .DATA_IN(DATA_IN), + .IADDER_OUT_1_TO_0(IADDER_OUT_reg[1:0]), + .OUTPUT(LU_OUTPUT) + + ); + + wire [31:0] alu_2nd_src_mux; + assign alu_2nd_src_mux = ALU_SRC_reg ? RS2_reg : IMM_reg; + + alu alu( + + .OP_1(RS1_reg), + .OP_2(alu_2nd_src_mux), + .OPCODE(ALU_OPCODE_reg), + .RESULT(ALU_RESULT) + + ); + + always @* + begin + case (WB_MUX_SEL_reg) + `WB_ALU: WB_MUX_OUT = ALU_RESULT; + `WB_LU: WB_MUX_OUT = LU_OUTPUT; + `WB_IMM: WB_MUX_OUT = IMM_reg; + `WB_IADDER_OUT: WB_MUX_OUT = IADDER_OUT_reg; + `WB_CSR: WB_MUX_OUT = CSR_DATA; + `WB_PC_PLUS: WB_MUX_OUT = PC_PLUS_4_reg; + default: WB_MUX_OUT = ALU_RESULT; + endcase + end + + // --------------------------------- + // OUTPUT ASSIGNMENTS + // --------------------------------- + + assign I_ADDR = PC_MUX_OUT; + assign WR_REQ = SU_WR_REQ; + assign WR_MASK = SU_WR_MASK; + assign D_ADDR = SU_D_ADDR; + assign DATA_OUT = SU_DATA_OUT; + +endmodule Index: steelcore/trunk/store_unit.v =================================================================== --- steelcore/trunk/store_unit.v (nonexistent) +++ steelcore/trunk/store_unit.v (revision 11) @@ -0,0 +1,170 @@ +////////////////////////////////////////////////////////////////////////////////// +// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com) +// +// Create Date: 02.06.2020 01:28:57 +// Module Name: store_unit +// Project Name: Steel Core +// Description: Controls the data memory interface +// +// Dependencies: - +// +// Version 0.01 +// +////////////////////////////////////////////////////////////////////////////////// + +/********************************************************************************* + +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----------------------------------------------------------------------------- + +Licença MIT + +Copyright (c) 2019 Rafael de Oliveira Calçada + +Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma +cópia deste software e dos arquivos de documentação associados +(o "Software"), para negociar sobre o Software sem restrições, incluindo, +sem limitação, os direitos de uso, cópia, modificação, fusão, publicação, +distribuição, sublicenciamento e/ou venda de cópias do Software e o direito +de permitir que pessoas a quem o Software seja fornecido o façam, sob as +seguintes condições: + +O aviso de direitos autorais acima e este aviso de permissão devem ser +incluídos em todas as cópias ou partes substanciais do Software. + +O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, +EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE +COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO. +EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO +RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, +SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO +COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE. + +********************************************************************************/ + +`timescale 1ns / 1ps +`include "globals.vh" + +module store_unit( + + input wire [1:0] FUNCT3, + input wire [31:0] IADDER_OUT, + input wire [31:0] RS2, + input wire MEM_WR_REQ, + output reg [31:0] DATA_OUT, + output wire [31:0] D_ADDR, + output reg [3:0] WR_MASK, + output wire WR_REQ + + ); + + reg [3:0] half_wr_mask; + reg [3:0] byte_wr_mask; + reg [31:0] half_dout; + reg [31:0] byte_dout; + + assign D_ADDR = {IADDER_OUT[31:2], 2'b0}; + assign WR_REQ = MEM_WR_REQ; + + always @* + begin + + case(FUNCT3[1:0]) + + 2'b00: WR_MASK = byte_wr_mask; + 2'b01: WR_MASK = half_wr_mask; + 2'b10: WR_MASK = {4{MEM_WR_REQ}}; + 2'b11: WR_MASK = {4{MEM_WR_REQ}}; + + endcase + + end + + always @* + begin + + case(FUNCT3[1:0]) + + 2'b00: DATA_OUT = byte_dout; + 2'b01: DATA_OUT = half_dout; + 2'b10: DATA_OUT = RS2; + 2'b11: DATA_OUT = RS2; + + endcase + + end + + always @* + begin + + case(IADDER_OUT[1:0]) + + 2'b00: byte_dout = {24'b0, RS2[7:0]}; + 2'b01: byte_dout = {16'b0, RS2[7:0], 8'b0}; + 2'b10: byte_dout = {8'b0, RS2[7:0], 16'b0}; + 2'b11: byte_dout = {RS2[7:0], 24'b0}; + + endcase + + end + + always @* + begin + + case(IADDER_OUT[1:0]) + + 2'b00: byte_wr_mask = {3'b0, MEM_WR_REQ}; + 2'b01: byte_wr_mask = {2'b0, MEM_WR_REQ, 1'b0}; + 2'b10: byte_wr_mask = {1'b0, MEM_WR_REQ, 2'b0}; + 2'b11: byte_wr_mask = {MEM_WR_REQ, 3'b0}; + + endcase + + end + + always @* + begin + + case(IADDER_OUT[1]) + + 1'b0: half_dout = {16'b0, RS2[15:0]}; + 1'b1: half_dout = {RS2[15:0], 16'b0}; + + endcase + + end + + always @* + begin + + case(IADDER_OUT[1]) + + 1'b0: half_wr_mask = {2'b0, {2{MEM_WR_REQ}}}; + 1'b1: half_wr_mask = {{2{MEM_WR_REQ}}, 2'b0}; + + endcase + + end + +endmodule Index: steelcore/LICENSE.md =================================================================== --- steelcore/LICENSE.md (nonexistent) +++ steelcore/LICENSE.md (revision 11) @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Rafael de Oliveira Calçada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.