master 0410b0fc0bc9 cached
30 files
58.4 KB
22.5k tokens
1 requests
Download .txt
Repository: mhyousefi/MIPS-pipeline-processor
Branch: master
Commit: 0410b0fc0bc9
Files: 30
Total size: 58.4 KB

Directory structure:
gitextract_pppgpag3/

├── .gitignore
├── README.md
├── alteraDE2SimulationFiles/
│   ├── 7segConv.v
│   └── DE2_TOP.V
├── defines.v
├── instructions/
│   ├── example_source_code.txt
│   └── rearrange_instructions.py
├── modules/
│   ├── ALU.v
│   ├── adder.v
│   ├── controlUnit/
│   │   ├── conditionChecker.v
│   │   └── controller.v
│   ├── hazard_forwarding/
│   │   ├── forwarding.v
│   │   └── hazardDetection.v
│   ├── memoryModules/
│   │   ├── dataMem.v
│   │   ├── instructionMem.v
│   │   └── regFile.v
│   ├── mux.v
│   ├── pipeRegisters/
│   │   ├── EXE2MEM.v
│   │   ├── ID2EXE.v
│   │   ├── IF2ID.v
│   │   └── MEM2WB.v
│   ├── pipeStages/
│   │   ├── EXEStage.v
│   │   ├── IDStage.v
│   │   ├── IFStage.v
│   │   ├── MEMStage.v
│   │   └── WBStage.v
│   ├── register.v
│   └── signExtend.v
├── testbench.v
└── topLevelCircuit.v

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.csv
*.mpf
*.qpf
*.qsf
*.v.bak
*.wlf
*.cr.mti
.DS_Store

configs/
db/
incremental_db/
output_files/
simulation/
work/
instructions/ready_instructions.txt


================================================
FILE: README.md
================================================
# MIPS-pipeline-processor

Thanks for visiting this repository!

Developed during the Fall 2017 Computer Architecture Laboratory course at the University of Tehran, 
this project is an implementation of a pipelined MIPS processor featuring hazard detection as well as forwarding.
This implementation is based on a limited ISA, the details for which are present in `docs/MIPS_ISA.png`.
This code is synthesizable and can be run on an FPGA. We used Altera DE2 units for testing purposes. The implemtation has been verified using a relatively complex test program (found in `instructions/example_source_code.txt`).

![MIPS pipelened processor](https://github.com/mhyousefi/MIPS-pipeline-processor/blob/master/docs/MIPS_diagram.png?raw=true)

## Getting Started

Download or clone the project, write your machine code to run (there already exists a default test program in the instruction memory),
compile the Verilog files and and run testbench.v in a Verilog simulation environment such as ModelSim from Mentor Graphics.

### Instruction format

Instructions should be provided to the instruction memory in reset time. We avoided the `readmemb` and `readmemh` functions to 
keep the code synthesizable. The instruction memory cells are 8 bits long, whereas each instruction is 32 bits long. 
Therefore, each instruction takes up four memory cells, as shown bellow.

For example, an add instruction: `10000000001000000000000000001010` or `Addi r1,r0,10` will need to be given as 

```
instMem[0] <= 8'b10000000;
instMem[1] <= 8'b00100000;
instMem[2] <= 8'b00000000;
instMem[3] <= 8'b00001010;
```

### Converting your raw machine codes

A python script is provided under the `instructions/rearrange_instructions.py` directory which simply takes your 
machine code (in a specified format) and converts it to the format illustrated above.

### Enable/disable forwarding

An instance of the top-level circuit is taken in `testbench.v`. 
The inputs of the `MIPS_Processor` include `clk`, `rst`, and `forwarding_EN`.
Forwarding will be enabled if `forwarding_EN` is set to 1, and disabled otherwise.

## Under the hood

There are five pipeline stages: 

1. Instruction Fetch
2. Instruction Decode
3. Execution
4. Memory
5. Write Back

### Modular design

All modules are organized under the `modules` directory.
The top level description can be found under `topLevelCircuit.v`. It contains a **modular design** of the processor and 
encompasses five pipe stages and four pipe registers, the description for which are present under `modules/pipeStages` and 
`modules/pipeRegisters` respectively. The register file, the hazard detection and the forwarding units are also instantiated
in `topLevelCircuit.v`. Pipe stages are made of and encapsulate other supporting modules.

### Constants

`defines.v` contains project-wide constants for **opcodes**, **execution commands**, and **branch condition commands**. 
It also contains constants for wire widths and memory specifications. You can change memory size values to suit your needs.

### Wire naming convention

To maintain conformity, most wire names follow the format {wire description}_{wire stage}, where the second part describes 
the stage where the wire is located. For example, `MEM_W_EN_ID` is the memory write enable signal present in the instruction decode stage.

## Contributions

Contributions are welcomed, both general improvements as well as new features such as a more realistic memory heirarchy or branch prediction. However, please follow the coding styles and the naming convention. Another useful contribution would be more comprehensive testing and verification and bug report.


================================================
FILE: alteraDE2SimulationFiles/7segConv.v
================================================
module sevenSegConv (num, out1, out2);
  input [31:0] num;
  output [6:0] out1, out2;

  wire [31:0] numLower = num / 10;
  wire [31:0] numUpper = num % 10;

  assign out1 = (numLower == 32'd0) ? 7'b1000000:
               (numLower == 32'd1) ? 7'b1001111:
               (numLower == 32'd2) ? 7'b0100100:
               (numLower == 32'd3) ? 7'b0110000:
               (numLower == 32'd4) ? 7'b0011001:
               (numLower == 32'd5) ? 7'b0010010:
               (numLower == 32'd6) ? 7'b0000010:
               (numLower == 32'd7) ? 7'b1111000:
               (numLower == 32'd8) ? 7'b0000000:
               (numLower == 32'd9) ? 7'b0010000: 7'b1111111;

 assign out2 = (numUpper == 32'd0) ? 7'b1000000:
              (numUpper == 32'd1) ? 7'b1001111:
              (numUpper == 32'd2) ? 7'b0100100:
              (numUpper == 32'd3) ? 7'b0110000:
              (numUpper == 32'd4) ? 7'b0011001:
              (numUpper == 32'd5) ? 7'b0010010:
              (numUpper == 32'd6) ? 7'b0000010:
              (numUpper == 32'd7) ? 7'b1111000:
              (numUpper == 32'd8) ? 7'b0000000:
              (numUpper == 32'd9) ? 7'b0010000: 7'b1111111;
endmodule // sevenSegConv


================================================
FILE: alteraDE2SimulationFiles/DE2_TOP.V
================================================
module DE2_TOP
	(
		////////////////////	Clock Input	 	////////////////////
		CLOCK_27,						//	27 MHz
		CLOCK_50,						//	50 MHz
		EXT_CLOCK,						//	External Clock
		////////////////////	Push Button		////////////////////
		KEY,							//	Pushbutton[3:0]
		////////////////////	DPDT Switch		////////////////////
		SW,								//	Toggle Switch[17:0]
		////////////////////	7-SEG Dispaly	////////////////////
		HEX0,							//	Seven Segment Digit 0
		HEX1,							//	Seven Segment Digit 1
		HEX2,							//	Seven Segment Digit 2
		HEX3,							//	Seven Segment Digit 3
		HEX4,							//	Seven Segment Digit 4
		HEX5,							//	Seven Segment Digit 5
		HEX6,							//	Seven Segment Digit 6
		HEX7,							//	Seven Segment Digit 7
		////////////////////////	LED		////////////////////////
		LEDG,							//	LED Green[8:0]
		LEDR,							//	LED Red[17:0]
		////////////////////////	UART	////////////////////////
		UART_TXD,						//	UART Transmitter
		UART_RXD,						//	UART Receiver
		////////////////////////	IRDA	////////////////////////
		// IRDA_TXD,						//	IRDA Transmitter
		// IRDA_RXD,						//	IRDA Receiver
		/////////////////////	SDRAM Interface		////////////////
		DRAM_DQ,						//	SDRAM Data bus 16 Bits
		DRAM_ADDR,						//	SDRAM Address bus 12 Bits
		DRAM_LDQM,						//	SDRAM Low-byte Data Mask
		DRAM_UDQM,						//	SDRAM High-byte Data Mask
		DRAM_WE_N,						//	SDRAM Write Enable
		DRAM_CAS_N,						//	SDRAM Column Address Strobe
		DRAM_RAS_N,						//	SDRAM Row Address Strobe
		DRAM_CS_N,						//	SDRAM Chip Select
		DRAM_BA_0,						//	SDRAM Bank Address 0
		DRAM_BA_1,						//	SDRAM Bank Address 0
		DRAM_CLK,						//	SDRAM Clock
		DRAM_CKE,						//	SDRAM Clock Enable
		////////////////////	Flash Interface		////////////////
		FL_DQ,							//	FLASH Data bus 8 Bits
		FL_ADDR,						//	FLASH Address bus 22 Bits
		FL_WE_N,						//	FLASH Write Enable
		FL_RST_N,						//	FLASH Reset
		FL_OE_N,						//	FLASH Output Enable
		FL_CE_N,						//	FLASH Chip Enable
		////////////////////	SRAM Interface		////////////////
		SRAM_DQ,						//	SRAM Data bus 16 Bits
		SRAM_ADDR,						//	SRAM Address bus 18 Bits
		SRAM_UB_N,						//	SRAM High-byte Data Mask
		SRAM_LB_N,						//	SRAM Low-byte Data Mask
		SRAM_WE_N,						//	SRAM Write Enable
		SRAM_CE_N,						//	SRAM Chip Enable
		SRAM_OE_N,						//	SRAM Output Enable
		////////////////////	ISP1362 Interface	////////////////
		OTG_DATA,						//	ISP1362 Data bus 16 Bits
		OTG_ADDR,						//	ISP1362 Address 2 Bits
		OTG_CS_N,						//	ISP1362 Chip Select
		OTG_RD_N,						//	ISP1362 Write
		OTG_WR_N,						//	ISP1362 Read
		OTG_RST_N,						//	ISP1362 Reset
		OTG_FSPEED,						//	USB Full Speed,	0 = Enable, Z = Disable
		OTG_LSPEED,						//	USB Low Speed, 	0 = Enable, Z = Disable
		OTG_INT0,						//	ISP1362 Interrupt 0
		OTG_INT1,						//	ISP1362 Interrupt 1
		OTG_DREQ0,						//	ISP1362 DMA Request 0
		OTG_DREQ1,						//	ISP1362 DMA Request 1
		OTG_DACK0_N,					//	ISP1362 DMA Acknowledge 0
		OTG_DACK1_N,					//	ISP1362 DMA Acknowledge 1
		////////////////////	LCD Module 16X2		////////////////
		LCD_ON,							//	LCD Power ON/OFF
		LCD_BLON,						//	LCD Back Light ON/OFF
		LCD_RW,							//	LCD Read/Write Select, 0 = Write, 1 = Read
		LCD_EN,							//	LCD Enable
		LCD_RS,							//	LCD Command/Data Select, 0 = Command, 1 = Data
		LCD_DATA,						//	LCD Data bus 8 bits
		////////////////////	SD_Card Interface	////////////////
		//SD_DAT,							//	SD Card Data
		SD_WP_N,						   //	SD Write protect
		SD_CMD,							//	SD Card Command Signal
		SD_CLK,							//	SD Card Clock
		////////////////////	USB JTAG link	////////////////////
		TDI,  							// CPLD -> FPGA (data in)
		TCK,  							// CPLD -> FPGA (clk)
		TCS,  							// CPLD -> FPGA (CS)
	   TDO,  							// FPGA -> CPLD (data out)
		////////////////////	I2C		////////////////////////////
		I2C_SDAT,						//	I2C Data
		I2C_SCLK,						//	I2C Clock
		////////////////////	PS2		////////////////////////////
		PS2_DAT,						//	PS2 Data
		PS2_CLK,						//	PS2 Clock
		////////////////////	VGA		////////////////////////////
		VGA_CLK,   						//	VGA Clock
		VGA_HS,							//	VGA H_SYNC
		VGA_VS,							//	VGA V_SYNC
		VGA_BLANK,						//	VGA BLANK
		VGA_SYNC,						//	VGA SYNC
		VGA_R,   						//	VGA Red[9:0]
		VGA_G,	 						//	VGA Green[9:0]
		VGA_B,  						//	VGA Blue[9:0]
		////////////	Ethernet Interface	////////////////////////
		ENET_DATA,						//	DM9000A DATA bus 16Bits
		ENET_CMD,						//	DM9000A Command/Data Select, 0 = Command, 1 = Data
		ENET_CS_N,						//	DM9000A Chip Select
		ENET_WR_N,						//	DM9000A Write
		ENET_RD_N,						//	DM9000A Read
		ENET_RST_N,						//	DM9000A Reset
		ENET_INT,						//	DM9000A Interrupt
		ENET_CLK,						//	DM9000A Clock 25 MHz
		////////////////	Audio CODEC		////////////////////////
		AUD_ADCLRCK,					//	Audio CODEC ADC LR Clock
		AUD_ADCDAT,						//	Audio CODEC ADC Data
		AUD_DACLRCK,					//	Audio CODEC DAC LR Clock
		AUD_DACDAT,						//	Audio CODEC DAC Data
		AUD_BCLK,						//	Audio CODEC Bit-Stream Clock
		AUD_XCK,						//	Audio CODEC Chip Clock
		////////////////	TV Decoder		////////////////////////
		TD_DATA,    					//	TV Decoder Data bus 8 bits
		TD_HS,							//	TV Decoder H_SYNC
		TD_VS,							//	TV Decoder V_SYNC
		TD_RESET,						//	TV Decoder Reset
		TD_CLK27,                  //	TV Decoder 27MHz CLK
		////////////////////	GPIO	////////////////////////////
		GPIO_0,							//	GPIO Connection 0
		GPIO_1							//	GPIO Connection 1
	);

////////////////////////	Clock Input	 	////////////////////////
input		   	CLOCK_27;				//	27 MHz
input		   	CLOCK_50;				//	50 MHz
input			   EXT_CLOCK;				//	External Clock
////////////////////////	Push Button		////////////////////////
input	   [3:0]	KEY;					//	Pushbutton[3:0]
////////////////////////	DPDT Switch		////////////////////////
input	  [17:0]	SW;						//	Toggle Switch[17:0]
////////////////////////	7-SEG Dispaly	////////////////////////
output	[6:0]	HEX0;					//	Seven Segment Digit 0
output	[6:0]	HEX1;					//	Seven Segment Digit 1
output	[6:0]	HEX2;					//	Seven Segment Digit 2
output	[6:0]	HEX3;					//	Seven Segment Digit 3
output	[6:0]	HEX4;					//	Seven Segment Digit 4
output	[6:0]	HEX5;					//	Seven Segment Digit 5
output	[6:0]	HEX6;					//	Seven Segment Digit 6
output	[6:0]	HEX7;					//	Seven Segment Digit 7
////////////////////////////	LED		////////////////////////////
output	[8:0]	LEDG;					//	LED Green[8:0]
output  [17:0]	LEDR;					//	LED Red[17:0]
////////////////////////////	UART	////////////////////////////
output			UART_TXD;				//	UART Transmitter
input			   UART_RXD;				//	UART Receiver
////////////////////////////	IRDA	////////////////////////////
//output			IRDA_TXD;				//	IRDA Transmitter
//input			   IRDA_RXD;				//	IRDA Receiver
///////////////////////		SDRAM Interface	////////////////////////
inout	  [15:0]	DRAM_DQ;				//	SDRAM Data bus 16 Bits
output  [11:0]	DRAM_ADDR;				//	SDRAM Address bus 12 Bits
output			DRAM_LDQM;				//	SDRAM Low-byte Data Mask
output			DRAM_UDQM;				//	SDRAM High-byte Data Mask
output			DRAM_WE_N;				//	SDRAM Write Enable
output			DRAM_CAS_N;				//	SDRAM Column Address Strobe
output			DRAM_RAS_N;				//	SDRAM Row Address Strobe
output			DRAM_CS_N;				//	SDRAM Chip Select
output			DRAM_BA_0;				//	SDRAM Bank Address 0
output			DRAM_BA_1;				//	SDRAM Bank Address 0
output			DRAM_CLK;				//	SDRAM Clock
output			DRAM_CKE;				//	SDRAM Clock Enable
////////////////////////	Flash Interface	////////////////////////
inout	  [7:0]	FL_DQ;					//	FLASH Data bus 8 Bits
output [21:0]	FL_ADDR;				//	FLASH Address bus 22 Bits
output			FL_WE_N;				//	FLASH Write Enable
output			FL_RST_N;				//	FLASH Reset
output			FL_OE_N;				//	FLASH Output Enable
output			FL_CE_N;				//	FLASH Chip Enable
////////////////////////	SRAM Interface	////////////////////////
inout	 [15:0]	SRAM_DQ;				//	SRAM Data bus 16 Bits
output [17:0]	SRAM_ADDR;				//	SRAM Address bus 18 Bits
output			SRAM_UB_N;				//	SRAM High-byte Data Mask
output			SRAM_LB_N;				//	SRAM Low-byte Data Mask
output			SRAM_WE_N;				//	SRAM Write Enable
output			SRAM_CE_N;				//	SRAM Chip Enable
output			SRAM_OE_N;				//	SRAM Output Enable
////////////////////	ISP1362 Interface	////////////////////////
inout	 [15:0]	OTG_DATA;				//	ISP1362 Data bus 16 Bits
output  [1:0]	OTG_ADDR;				//	ISP1362 Address 2 Bits
output			OTG_CS_N;				//	ISP1362 Chip Select
output			OTG_RD_N;				//	ISP1362 Write
output			OTG_WR_N;				//	ISP1362 Read
output			OTG_RST_N;				//	ISP1362 Reset
output			OTG_FSPEED;				//	USB Full Speed,	0 = Enable, Z = Disable
output			OTG_LSPEED;				//	USB Low Speed, 	0 = Enable, Z = Disable
input			   OTG_INT0;				//	ISP1362 Interrupt 0
input			   OTG_INT1;				//	ISP1362 Interrupt 1
input			   OTG_DREQ0;				//	ISP1362 DMA Request 0
input			   OTG_DREQ1;				//	ISP1362 DMA Request 1
output			OTG_DACK0_N;			//	ISP1362 DMA Acknowledge 0
output			OTG_DACK1_N;			//	ISP1362 DMA Acknowledge 1
////////////////////	LCD Module 16X2	////////////////////////////
inout	  [7:0]	LCD_DATA;				//	LCD Data bus 8 bits
output			LCD_ON;					//	LCD Power ON/OFF
output			LCD_BLON;				//	LCD Back Light ON/OFF
output			LCD_RW;					//	LCD Read/Write Select, 0 = Write, 1 = Read
output			LCD_EN;					//	LCD Enable
output			LCD_RS;					//	LCD Command/Data Select, 0 = Command, 1 = Data
////////////////////	SD Card Interface	////////////////////////
//inout	 [3:0]	SD_DAT;					//	SD Card Data
input			   SD_WP_N;				   //	SD write protect
inout			   SD_CMD;					//	SD Card Command Signal
output			SD_CLK;					//	SD Card Clock
////////////////////////	I2C		////////////////////////////////
inout			   I2C_SDAT;				//	I2C Data
output			I2C_SCLK;				//	I2C Clock
////////////////////////	PS2		////////////////////////////////
input		 	   PS2_DAT;				//	PS2 Data
input			   PS2_CLK;				//	PS2 Clock
////////////////////	USB JTAG link	////////////////////////////
input  			TDI;					// CPLD -> FPGA (data in)
input  			TCK;					// CPLD -> FPGA (clk)
input  			TCS;					// CPLD -> FPGA (CS)
output 			TDO;					// FPGA -> CPLD (data out)
////////////////////////	VGA			////////////////////////////
output			VGA_CLK;   				//	VGA Clock
output			VGA_HS;					//	VGA H_SYNC
output			VGA_VS;					//	VGA V_SYNC
output			VGA_BLANK;				//	VGA BLANK
output			VGA_SYNC;				//	VGA SYNC
output	[9:0]	VGA_R;   				//	VGA Red[9:0]
output	[9:0]	VGA_G;	 				//	VGA Green[9:0]
output	[9:0]	VGA_B;   				//	VGA Blue[9:0]
////////////////	Ethernet Interface	////////////////////////////
inout	[15:0]	ENET_DATA;				//	DM9000A DATA bus 16Bits
output			ENET_CMD;				//	DM9000A Command/Data Select, 0 = Command, 1 = Data
output			ENET_CS_N;				//	DM9000A Chip Select
output			ENET_WR_N;				//	DM9000A Write
output			ENET_RD_N;				//	DM9000A Read
output			ENET_RST_N;				//	DM9000A Reset
input			   ENET_INT;				//	DM9000A Interrupt
output			ENET_CLK;				//	DM9000A Clock 25 MHz
////////////////////	Audio CODEC		////////////////////////////
inout			   AUD_ADCLRCK;			//	Audio CODEC ADC LR Clock
input			   AUD_ADCDAT;				//	Audio CODEC ADC Data
inout			   AUD_DACLRCK;			//	Audio CODEC DAC LR Clock
output			AUD_DACDAT;				//	Audio CODEC DAC Data
inout			   AUD_BCLK;				//	Audio CODEC Bit-Stream Clock
output			AUD_XCK;				//	Audio CODEC Chip Clock
////////////////////	TV Devoder		////////////////////////////
input	 [7:0]	TD_DATA;    			//	TV Decoder Data bus 8 bits
input			   TD_HS;					//	TV Decoder H_SYNC
input			   TD_VS;					//	TV Decoder V_SYNC
output			TD_RESET;				//	TV Decoder Reset
input          TD_CLK27;            //	TV Decoder 27MHz CLK
////////////////////////	GPIO	////////////////////////////////
inout	[35:0]	GPIO_0;					//	GPIO Connection 0
inout	[35:0]	GPIO_1;					//	GPIO Connection 1
	wire clock = CLOCK_50;
	wire [31:0] PC_IF, PC_ID, PC_EXE, PC_MEM;
	wire [31:0] inst_IF, inst_ID;
	wire [31:0] reg1_ID, reg2_ID, ST_value_EXE, ST_value_EXE2MEM, ST_value_MEM;
	wire [31:0] val1_ID, val1_EXE;
	wire [31:0] val2_ID, val2_EXE;
	wire [31:0] ALURes_EXE, ALURes_MEM, ALURes_WB;
	wire [31:0] dataMem_out_MEM, dataMem_out_WB;
	wire [31:0] WB_result;
	wire [4:0] dest_EXE, dest_MEM, dest_WB; // dest_ID = instruction[25:21] thus nothing declared
	wire [4:0] src1_ID, src2_regFile_ID, src2_forw_ID, src2_forw_EXE, src1_forw_EXE;
	wire [3:0] EXE_CMD_ID, EXE_CMD_EXE;
	wire [1:0] val1_sel, val2_sel, ST_val_sel;
	wire [1:0] branch_comm;
	wire Br_Taken_ID, IF_Flush, Br_Taken_EXE;
	wire MEM_R_EN_ID, MEM_R_EN_EXE, MEM_R_EN_MEM, MEM_R_EN_WB;
	wire MEM_W_EN_ID, MEM_W_EN_EXE, MEM_W_EN_MEM;
	wire WB_EN_ID, WB_EN_EXE, WB_EN_MEM, WB_EN_WB;
	wire hazard_detected, is_imm, ST_or_BNE;

	regFile regFile(
		// INPUTS
		.clk(clock),
		.rst(SW[0]),
		.src1(src1_ID),
		.src2(src2_regFile_ID),
		.dest(dest_WB),
		.writeVal(WB_result),
		.writeEn(WB_EN_WB),
		// OUTPUTS
		.reg1(reg1_ID),
		.reg2(reg2_ID)
	);

	hazard_detection hazard (
		// INPUTS
		.forward_EN(SW[1]),
		.is_imm(is_imm),
		.ST_or_BNE(ST_or_BNE),
		.src1_ID(src1_ID),
		.src2_ID(src2_regFile_ID),
		.dest_EXE(dest_EXE),
		.dest_MEM(dest_MEM),
		.WB_EN_EXE(WB_EN_EXE),
		.WB_EN_MEM(WB_EN_MEM),
		.MEM_R_EN_EXE(MEM_R_EN_EXE),
		// OUTPUTS
		.branch_comm(branch_comm),
		.hazard_detected(hazard_detected)
	);

	forwarding_EXE forwrding_EXE (
		.src1_EXE(src1_forw_EXE),
		.src2_EXE(src2_forw_EXE),
		.ST_src_EXE(dest_EXE),
		.dest_MEM(dest_MEM),
		.dest_WB(dest_WB),
		.WB_EN_MEM(WB_EN_MEM),
		.WB_EN_WB(WB_EN_WB),
		.val1_sel(val1_sel),
		.val2_sel(val2_sel),
		.ST_val_sel(ST_val_sel)
	);

	//###########################
	//##### PIPLINE STAGES ######
	//###########################
	IFStage IFStage (
		// INPUTS
		.clk(clock),
		.rst(SW[0]),
		.freeze(hazard_detected),
		.brTaken(Br_Taken_ID),
		.brOffset(val2_ID),
		// OUTPUTS
		.instruction(inst_IF),
		.PC(PC_IF)
	);

	IDStage IDStage (
		// INPUTS
		.clk(clock),
		.rst(SW[0]),
		.hazard_detected_in(hazard_detected),
		.instruction(inst_ID),
		.reg1(reg1_ID),
		.reg2(reg2_ID),
		// OUTPUTS
		.src1(src1_ID),
		.src2_reg_file(src2_regFile_ID),
		.src2_forw(src2_forw_ID),
		.val1(val1_ID),
		.val2(val2_ID),
		.brTaken(Br_Taken_ID),
		.EXE_CMD(EXE_CMD_ID),
		.MEM_R_EN(MEM_R_EN_ID),
		.MEM_W_EN(MEM_W_EN_ID),
		.WB_EN(WB_EN_ID),
		.is_imm_out(is_imm),
		.ST_or_BNE_out(ST_or_BNE),
		.branch_comm(branch_comm)
	);

	EXEStage EXEStage (
		// INPUTS
		.clk(clock),
		.EXE_CMD(EXE_CMD_EXE),
		.val1_sel(val1_sel),
		.val2_sel(val2_sel),
		.ST_val_sel(ST_val_sel),
		.val1(val1_EXE),
		.val2(val2_EXE),
		.ALU_res_MEM(ALURes_MEM),
		.result_WB(WB_result),
		.ST_value_in(ST_value_EXE),
		// OUTPUTS
		.ALUResult(ALURes_EXE),
		.ST_value_out(ST_value_EXE2MEM)
	);

	MEMStage MEMStage (
		// INPUTS
		.clk(clock),
		.rst(SW[0]),
		.MEM_R_EN(MEM_R_EN_MEM),
		.MEM_W_EN(MEM_W_EN_MEM),
		.ALU_res(ALURes_MEM),
		.ST_value(ST_value_MEM),
		// OUTPUTS
		.dataMem_out(dataMem_out_MEM)
	);

	WBStage WBStage (
		// INPUTS
		.MEM_R_EN(MEM_R_EN_WB),
		.memData(dataMem_out_WB),
		.aluRes(ALURes_WB),
		// OUTPUTS
		.WB_res(WB_result)
	);

	//###########################
	//#### PIPLINE REISTERS #####
	//###########################
	IF2ID IF2IDReg (
		// INPUTS
		.clk(clock),
		.rst(SW[0]),
		.flush(IF_Flush),
		.freeze(hazard_detected),
		.PCIn(PC_IF),
		.instructionIn(inst_IF),
		// OUTPUTS
		.PC(PC_ID),
		.instruction(inst_ID)
	);

	ID2EXE ID2EXEReg (
		.clk(clock),
		.rst(SW[0]),
		// INPUTS
		.destIn(inst_ID[25:21]),
		.src1_in(src1_ID),
		.src2_in(src2_forw_ID),
		.reg2In(reg2_ID),
		.val1In(val1_ID),
		.val2In(val2_ID),
		.PCIn(PC_ID),
		.EXE_CMD_IN(EXE_CMD_ID),
		.MEM_R_EN_IN(MEM_R_EN_ID),
		.MEM_W_EN_IN(MEM_W_EN_ID),
		.WB_EN_IN(WB_EN_ID),
		.brTaken_in(Br_Taken_ID),
		// OUTPUTS
		.src1_out(src1_forw_EXE),
		.src2_out(src2_forw_EXE),
		.dest(dest_EXE),
		.ST_value(ST_value_EXE),
		.val1(val1_EXE),
		.val2(val2_EXE),
		.PC(PC_EXE),
		.EXE_CMD(EXE_CMD_EXE),
		.MEM_R_EN(MEM_R_EN_EXE),
		.MEM_W_EN(MEM_W_EN_EXE),
		.WB_EN(WB_EN_EXE),
		.brTaken_out(Br_Taken_EXE)
	);

	EXE2MEM EXE2MEMReg (
		.clk(clock),
		.rst(SW[0]),
		// INPUTS
		.WB_EN_IN(WB_EN_EXE),
		.MEM_R_EN_IN(MEM_R_EN_EXE),
		.MEM_W_EN_IN(MEM_W_EN_EXE),
		.PCIn(PC_EXE),
		.ALUResIn(ALURes_EXE),
		.STValIn(ST_value_EXE2MEM),
		.destIn(dest_EXE),
		// OUTPUTS
		.WB_EN(WB_EN_MEM),
		.MEM_R_EN(MEM_R_EN_MEM),
		.MEM_W_EN(MEM_W_EN_MEM),
		.PC(PC_MEM),
		.ALURes(ALURes_MEM),
		.STVal(ST_value_MEM),
		.dest(dest_MEM)
	);

	MEM2WB MEM2WB(
		.clk(clock),
		.rst(SW[0]),
		// INPUTS
		.WB_EN_IN(WB_EN_MEM),
		.MEM_R_EN_IN(MEM_R_EN_MEM),
		.ALUResIn(ALURes_MEM),
		.memReadValIn(dataMem_out_MEM),
		.destIn(dest_MEM),
		// OUTPUTS
		.WB_EN(WB_EN_WB),
		.MEM_R_EN(MEM_R_EN_WB),
		.ALURes(ALURes_WB),
		.memReadVal(dataMem_out_WB),
		.dest(dest_WB)
	);

	assign IF_Flush = Br_Taken_ID;
endmodule


================================================
FILE: defines.v
================================================
// Wire widths
`define WORD_LEN 32
`define REG_FILE_ADDR_LEN 5
`define EXE_CMD_LEN 4
`define FORW_SEL_LEN 2
`define OP_CODE_LEN 6

// Memory constants
`define DATA_MEM_SIZE 1024
`define INSTR_MEM_SIZE 1024
`define REG_FILE_SIZE 32
`define MEM_CELL_SIZE 8

// To be used inside controller.v
`define OP_NOP 6'b000000
`define OP_ADD 6'b000001
`define OP_SUB 6'b000011
`define OP_AND 6'b000101
`define OP_OR 6'b000110
`define OP_NOR 6'b000111
`define OP_XOR 6'b001000
`define OP_SLA 6'b001001
`define OP_SLL 6'b001010
`define OP_SRA 6'b001011
`define OP_SRL 6'b001100
`define OP_ADDI 6'b100000
`define OP_SUBI 6'b100001
`define OP_LD 6'b100100
`define OP_ST 6'b100101
`define OP_BEZ 6'b101000
`define OP_BNE 6'b101001
`define OP_JMP 6'b101010

// To be used in side ALU
`define EXE_ADD 4'b0000
`define EXE_SUB 4'b0010
`define EXE_AND 4'b0100
`define EXE_OR 4'b0101
`define EXE_NOR 4'b0110
`define EXE_XOR 4'b0111
`define EXE_SLA 4'b1000
`define EXE_SLL 4'b1000
`define EXE_SRA 4'b1001
`define EXE_SRL 4'b1010
`define EXE_NO_OPERATION 4'b1111 // for NOP, BEZ, BNQ, JMP

// To be used in conditionChecker
`define COND_JUMP 2'b10
`define COND_BEZ 2'b11
`define COND_BNE 2'b01
`define COND_NOTHING 2'b00


================================================
FILE: instructions/example_source_code.txt
================================================
10000000001000000000000000001010; Addi r1,r0,10		*** (1 begins) performing basic arithmetic operations
00000100010000000000100000000000; Add  r2,r0,r1		***
00001100011000000000100000000000; sub r3,r0,r1		***
00010100100000100001100000000000; And r4,r2,r3		***
10000100101000000000001000110100; Subi r5,r0,564		***
00011000101001010001100000000000; or r5,r5,r3		***
00011100110001010000000000000000; nor  r6,r5,r0		***
00100000000001010000100000000000; xor r0,r5,r1		***
00100000111001010000100000000000; xor r7,r5,r1		***
00100100111001000001000000000000; sla r7,r4,r2		***
00101001000000110001000000000000; sll r8,r3,r2		***
00101101001001100001000000000000; sra r9,r6,r2		***
00110001010001100001000000000000; srl r10,r6,r2		*** (1 ends)
10000000001000000000010000000000; Addi r1,r0,1024		*** (2 begins) exchanging some data with the memory
10010100010000010000000000000000; st r2,r1,0		***
10010001011000010000000000000000; ld r11,r1,0		***
10010100011000010000000000000100; st r3,r1,4		***
10010100100000010000000000001000; st r4,r1,8		***
10010100101000010000000000001100; st r5,r1,12		***
10010100110000010000000000010000; st r6,r1,16		***
10010100111000010000000000010100; st r7,r1,20		***
10010101000000010000000000011000; st r8,r1,24		***
10010101001000010000000000011100; st r9,r1,28		***
10010101010000010000000000100000; st r10,r1,32		***
10010101011000010000000000100100; st r11,r1,36		*** (2 ends)
10000000001000000000000000000011; Addi  r1,r0,3		*** =====> BUBBLE SORT BEGINS
10000000100000000000010000000000; Addi r4,r0,1024		***
10000000010000000000000000000000; Addi  r2,r0,0		***
10000000011000000000000000000001; Addi  r3,r0,1 		*** (outer loop begins)
10000001001000000000000000000010; Addi  r9,r0,2 		*** (inner loop begins)
00101001000000110100100000000000; sll r8,r3,r9		*** (3 begins) loading two consecutive numbers to compare
00000101000001000100000000000000; Add  r8,r4,r8		***
10010000101010000000000000000000; ld r5,r8,0 		***
10010000110010001111111111111100; ld r6,r8,-4 		***
00001101001001010011000000000000; sub  r9,r5,r6 		***
10000001010000001000000000000000; Addi  r10,r0,0x8000	***
10000001011000000000000000010000; Addi r11,r0,16		***
00101001010010100101100000000000; sll r10,r10,r11		***
00010101001010010101000000000000; And r9,r9,r10		*** (3 ends)
10100000000010010000000000000010; Bez r9,2 		*** (4 begins) swapping the two loaded numbers if needed
10010100101010001111111111111100; st r5,r8,-4 		***
10010100110010000000000000000000; st r6,r8,0 		*** (4 ends)
10000000011000110000000000000001; Addi  r3,r3,1		*** R3++
10100100011000011111111111110001; BNE r3,r1,-15 		*** (inner loop ends)
10000000010000100000000000000001; Addi  r2,r2,1		*** R2++
10100100010000011111111111101110; BNE r2,r1,-18 		*** (outer loop ends) =====> BUBBLE SORT ENDS
10000000001000000000010000000000; Addi  r1,r0,1024 	*** (5 begins) storing some register inside memory
10010000010000010000000000000000; ld r2,r1,0		***
10010000011000010000000000000100; ld r3,r1,4		***
10010000100000010000000000001000; ld r4,r1,8		***
10010000101000010000000000001100; ld r5,r1,12		***
10010000110000010000000000010000; ld r6,r1,16		***
10010000111000010000000000010100; ld r7,r1,20		***
10010001000000010000000000011000; ld r8,r1,24		***
10010001001000010000000000011100; ld r9,r1,28		***
10010001010000010000000000100000; ld r10,r1,32		***
10010001011000010000000000100100; ld r11,r1,36		*** (5 ends)
10101000000000001111111111111111; JMP  -1 			*** will keep jumping to itself


================================================
FILE: instructions/rearrange_instructions.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Rearranging instructions from a source file to a format suitable for the always statement under instructionMem.v
# There is an example source code under this directory
# In drafting your own code, make sure you follow the ISA in this project

DESTINATION_FILE_NAME = "ready_instructions.txt"
INSTR_MEM_ARRAY_NAME = "instMem"

line_count = int(raw_input("Enter the number of instructions to rearrange: "))
source_file_name = raw_input("Enter the source file name: ")

instructions = []

with open(source_file_name, "r") as instr_file:
    for i in range(line_count):
        instructions.append(instr_file.readline()[:-1])

with open(DESTINATION_FILE_NAME, "w") as dest_file:
    for i in range(len(instructions)):
        instr = instructions[i]
        dest_file.write(INSTR_MEM_ARRAY_NAME + "[" + str(i*4)   + "] <= 8'b" + instr[0:8] + "; // ==> " + instr[34:] + "\n")
        dest_file.write(INSTR_MEM_ARRAY_NAME + "[" + str(i*4+1) + "] <= 8'b" + instr[8:16] + ";\n")
        dest_file.write(INSTR_MEM_ARRAY_NAME + "[" + str(i*4+2) + "] <= 8'b" + instr[16:24] + ";\n")
        dest_file.write(INSTR_MEM_ARRAY_NAME + "[" + str(i*4+3) + "] <= 8'b" + instr[24:32] + ";\n\n")


print "💡💡💡 ==> instructions reformatted for instruction memory."
print "To run them, copy and paste the content of ready_instructions.txt under the reset if statement in the instructionMem.v always statement."


================================================
FILE: modules/ALU.v
================================================
`include "defines.v"

module ALU (val1, val2, EXE_CMD, aluOut);
  input [`WORD_LEN-1:0] val1, val2;
  input [`EXE_CMD_LEN-1:0] EXE_CMD;
  output reg [`WORD_LEN-1:0] aluOut;

  always @ ( * ) begin
    case (EXE_CMD)
      `EXE_ADD: aluOut <= val1 + val2;
      `EXE_SUB: aluOut <= val1 - val2;
      `EXE_AND: aluOut <= val1 & val2;
      `EXE_OR: aluOut <= val1 | val2;
      `EXE_NOR: aluOut <= ~(val1 | val2);
      `EXE_XOR: aluOut <= val1 ^ val2;
      `EXE_SLA: aluOut <= val1 << val2;
      `EXE_SLL: aluOut <= val1 <<< val2;
      `EXE_SRA: aluOut <= val1 >> val2;
      `EXE_SRL: aluOut <= val1 >>> val2;
      default: aluOut <= 0;
    endcase
  end
endmodule // ALU


================================================
FILE: modules/adder.v
================================================
`include "defines.v"

module adder (in1, in2, out);
  input [`WORD_LEN-1:0] in1, in2;
  output [`WORD_LEN-1:0] out;

  assign out = in1 + in2;
endmodule // adder


================================================
FILE: modules/controlUnit/conditionChecker.v
================================================
`include "defines.v"

module conditionChecker (reg1, reg2, cuBranchComm, brCond);
  input [`WORD_LEN-1: 0] reg1, reg2;
  input [1:0] cuBranchComm;
  output reg brCond;

  always @ ( * ) begin
    case (cuBranchComm)
      `COND_JUMP: brCond <= 1;
      `COND_BEZ: brCond <= (reg1 == 0) ? 1 : 0;
      `COND_BNE: brCond <= (reg1 != reg2) ? 1 : 0;
      default: brCond <= 0;
    endcase
  end
endmodule // conditionChecker


================================================
FILE: modules/controlUnit/controller.v
================================================
`include "defines.v"

module controller (opCode, branchEn, EXE_CMD, Branch_command, Is_Imm, ST_or_BNE, WB_EN, MEM_R_EN, MEM_W_EN, hazard_detected);
  input hazard_detected;
  input [`OP_CODE_LEN-1:0] opCode;
  output reg branchEn;
  output reg [`EXE_CMD_LEN-1:0] EXE_CMD;
  output reg [1:0] Branch_command;
  output reg Is_Imm, ST_or_BNE, WB_EN, MEM_R_EN, MEM_W_EN;

  always @ ( * ) begin
    if (hazard_detected == 0) begin
      {branchEn, EXE_CMD, Branch_command, Is_Imm, ST_or_BNE, WB_EN, MEM_R_EN, MEM_W_EN} <= 0;
      case (opCode)
        // operations writing to the register file
        `OP_ADD: begin EXE_CMD <= `EXE_ADD; WB_EN <= 1; end
        `OP_SUB: begin EXE_CMD <= `EXE_SUB; WB_EN <= 1; end
        `OP_AND: begin EXE_CMD <= `EXE_AND; WB_EN <= 1; end
        `OP_OR:  begin EXE_CMD <= `EXE_OR;  WB_EN <= 1; end
        `OP_NOR: begin EXE_CMD <= `EXE_NOR; WB_EN <= 1; end
        `OP_XOR: begin EXE_CMD <= `EXE_XOR; WB_EN <= 1; end
        `OP_SLA: begin EXE_CMD <= `EXE_SLA; WB_EN <= 1; end
        `OP_SLL: begin EXE_CMD <= `EXE_SLL; WB_EN <= 1; end
        `OP_SRA: begin EXE_CMD <= `EXE_SRA; WB_EN <= 1; end
        `OP_SRL: begin EXE_CMD <= `EXE_SRL; WB_EN <= 1; end
        // operations using an immediate value embedded in the instruction
        `OP_ADDI: begin EXE_CMD <= `EXE_ADD; WB_EN <= 1; Is_Imm <= 1; end
        `OP_SUBI: begin EXE_CMD <= `EXE_SUB; WB_EN <= 1; Is_Imm <= 1; end
        // memory operations
        `OP_LD: begin EXE_CMD <= `EXE_ADD; WB_EN <= 1; Is_Imm <= 1; ST_or_BNE <= 1; MEM_R_EN <= 1; end
        `OP_ST: begin EXE_CMD <= `EXE_ADD; Is_Imm <= 1; MEM_W_EN <= 1; ST_or_BNE <= 1; end
        // branch operations
        `OP_BEZ: begin EXE_CMD <= `EXE_NO_OPERATION; Is_Imm <= 1; Branch_command <= `COND_BEZ; branchEn <= 1; end
        `OP_BNE: begin EXE_CMD <= `EXE_NO_OPERATION; Is_Imm <= 1; Branch_command <= `COND_BNE; branchEn <= 1; ST_or_BNE <= 1; end
        `OP_JMP: begin EXE_CMD <= `EXE_NO_OPERATION; Is_Imm <= 1; Branch_command <= `COND_JUMP; branchEn <= 1; end
        default: {branchEn, EXE_CMD, Branch_command, Is_Imm, ST_or_BNE, WB_EN, MEM_R_EN, MEM_W_EN} <= 0;
      endcase
    end

    else if (hazard_detected ==  1) begin
      // preventing any writes to the register file or the memory
      {EXE_CMD, WB_EN, MEM_W_EN} <= 0;
    end
  end
endmodule // controller


================================================
FILE: modules/hazard_forwarding/forwarding.v
================================================
`include "defines.v"

module forwarding_EXE (src1_EXE, src2_EXE, ST_src_EXE, dest_MEM, dest_WB, WB_EN_MEM, WB_EN_WB, val1_sel, val2_sel, ST_val_sel);
  input [`REG_FILE_ADDR_LEN-1:0] src1_EXE, src2_EXE, ST_src_EXE;
  input [`REG_FILE_ADDR_LEN-1:0] dest_MEM, dest_WB;
  input WB_EN_MEM, WB_EN_WB;
  output reg [`FORW_SEL_LEN-1:0] val1_sel, val2_sel, ST_val_sel;

  always @ ( * ) begin
    // initializing sel signals to 0
    // they will change to enable forwrding if needed.
    {val1_sel, val2_sel, ST_val_sel} <= 0;

    // determining forwarding control signal for store value (ST_val)
    if (WB_EN_MEM && ST_src_EXE == dest_MEM) ST_val_sel <= 2'd1;
    else if (WB_EN_WB && ST_src_EXE == dest_WB) ST_val_sel <= 2'd2;

    // determining forwarding control signal for ALU val1
    if (WB_EN_MEM && src1_EXE == dest_MEM) val1_sel <= 2'd1;
    else if (WB_EN_WB && src1_EXE == dest_WB) val1_sel <= 2'd2;

    // determining forwarding control signal for ALU val2
    if (WB_EN_MEM && src2_EXE == dest_MEM) val2_sel <= 2'd1;
    else if (WB_EN_WB && src2_EXE == dest_WB) val2_sel <= 2'd2;
  end
endmodule // forwarding


================================================
FILE: modules/hazard_forwarding/hazardDetection.v
================================================
`include "defines.v"

module hazard_detection(forward_EN, is_imm, ST_or_BNE, src1_ID, src2_ID, dest_EXE, WB_EN_EXE, dest_MEM, WB_EN_MEM, MEM_R_EN_EXE, branch_comm, hazard_detected);
  input [`REG_FILE_ADDR_LEN-1:0] src1_ID, src2_ID;
  input [`REG_FILE_ADDR_LEN-1:0] dest_EXE, dest_MEM;
  input [1:0] branch_comm;
  input forward_EN, WB_EN_EXE, WB_EN_MEM, is_imm, ST_or_BNE, MEM_R_EN_EXE;
  output hazard_detected;

  wire src2_is_valid, exe_has_hazard, mem_has_hazard, hazard, instr_is_branch;

  assign src2_is_valid =  (~is_imm) || ST_or_BNE;

  assign exe_has_hazard = WB_EN_EXE && (src1_ID == dest_EXE || (src2_is_valid && src2_ID == dest_EXE));
  assign mem_has_hazard = WB_EN_MEM && (src1_ID == dest_MEM || (src2_is_valid && src2_ID == dest_MEM));

  assign hazard = (exe_has_hazard || mem_has_hazard);
  assign instr_is_branch = (branch_comm == `COND_BEZ || branch_comm == `COND_BNE);

  assign hazard_detected = ~forward_EN ? hazard : (instr_is_branch && hazard) || (MEM_R_EN_EXE && mem_has_hazard);
endmodule // hazard_detection


================================================
FILE: modules/memoryModules/dataMem.v
================================================
`include "defines.v"

module dataMem (clk, rst, writeEn, readEn, address, dataIn, dataOut);
  input clk, rst, readEn, writeEn;
  input [`WORD_LEN-1:0] address, dataIn;
  output [`WORD_LEN-1:0] dataOut;

  integer i;
  reg [`MEM_CELL_SIZE-1:0] dataMem [0:`DATA_MEM_SIZE-1];
  wire [`WORD_LEN-1:0] base_address;

  always @ (posedge clk) begin
    if (rst)
      for (i = 0; i < `DATA_MEM_SIZE; i = i + 1)
        dataMem[i] <= 0;
    else if (writeEn)
      {dataMem[base_address], dataMem[base_address + 1], dataMem[base_address + 2], dataMem[base_address + 3]} <= dataIn;
  end

  assign base_address = ((address & 32'b11111111111111111111101111111111) >> 2) << 2;
  assign dataOut = (address < 1024) ? 0 : {dataMem[base_address], dataMem[base_address + 1], dataMem[base_address + 2], dataMem[base_address + 3]};
endmodule // dataMem


================================================
FILE: modules/memoryModules/instructionMem.v
================================================
`include "defines.v"

module instructionMem (rst, addr, instruction);
  input rst;
  input [`WORD_LEN-1:0] addr;
  output [`WORD_LEN-1:0] instruction;

  wire [$clog2(`INSTR_MEM_SIZE)-1:0] address = addr[$clog2(`INSTR_MEM_SIZE)-1:0];
  reg [`MEM_CELL_SIZE-1:0] instMem [0:`INSTR_MEM_SIZE-1];

  always @ (*) begin
  	if (rst) begin
        // No nop added in between instructions since there is a hazard detection unit

        instMem[0] <= 8'b10000000; //-- Addi	r1,r0,10
        instMem[1] <= 8'b00100000;
        instMem[2] <= 8'b00000000;
        instMem[3] <= 8'b00001010;

        instMem[4] <= 8'b00000100; //-- Add 	r2,r0,r1
        instMem[5] <= 8'b01000000;
        instMem[6] <= 8'b00001000;
        instMem[7] <= 8'b00000000;

        instMem[8] <= 8'b00001100; //-- sub	r3,r0,r1
        instMem[9] <= 8'b01100000;
        instMem[10] <= 8'b00001000;
        instMem[11] <= 8'b00000000;

        instMem[12] <= 8'b00010100; //-- And	r4,r2,r3
        instMem[13] <= 8'b10000010;
        instMem[14] <= 8'b00011000;
        instMem[15] <= 8'b00000000;

        instMem[16] <= 8'b10000100; //-- Subi	r5,r0,564
        instMem[17] <= 8'b10100000;
        instMem[18] <= 8'b00000010;
        instMem[19] <= 8'b00110100;

        instMem[20] <= 8'b00011000; //-- or	r5,r5,r3
        instMem[21] <= 8'b10100101;
        instMem[22] <= 8'b00011000;
        instMem[23] <= 8'b00000000;

        instMem[24] <= 8'b00011100; //-- nor 	r6,r5,r0
        instMem[25] <= 8'b11000101;
        instMem[26] <= 8'b00000000;
        instMem[27] <= 8'b00000000;

        instMem[28] <= 8'b00100000; //-- xor	r0,r5,r1
        instMem[29] <= 8'b00000101;
        instMem[30] <= 8'b00001000;
        instMem[31] <= 8'b00000000;

        instMem[32] <= 8'b00100000; //-- xor	r7,r5,r0
        instMem[33] <= 8'b11100101;
        instMem[34] <= 8'b00001000;
        instMem[35] <= 8'b00000000;

        instMem[36] <= 8'b00100100; //-- sla	r7,r4,r2
        instMem[37] <= 8'b11100100;
        instMem[38] <= 8'b00010000;
        instMem[39] <= 8'b00000000;

        instMem[40] <= 8'b00101001; //-- sll	r8,r3,r2
        instMem[41] <= 8'b00000011;
        instMem[42] <= 8'b00010000;
        instMem[43] <= 8'b00000000;

        instMem[44] <= 8'b00101101; //-- sra	r9,r6,r2
        instMem[45] <= 8'b00100110;
        instMem[46] <= 8'b00010000;
        instMem[47] <= 8'b00000000;

        instMem[48] <= 8'b00110001; //-- srl	r10,r6,r2
        instMem[49] <= 8'b01000110;
        instMem[50] <= 8'b00010000;
        instMem[51] <= 8'b00000000;

        instMem[52] <= 8'b10000000; //-- Addi 	r1,r0,1024
        instMem[53] <= 8'b00100000;
        instMem[54] <= 8'b00000100;
        instMem[55] <= 8'b00000000;

        instMem[56] <= 8'b10010100; //-- st	r2,r1,0
        instMem[57] <= 8'b01000001;
        instMem[58] <= 8'b00000000;
        instMem[59] <= 8'b00000000;

        instMem[60] <= 8'b10010001; //-- ld	r11,r1,0
        instMem[61] <= 8'b01100001;
        instMem[62] <= 8'b00000000;
        instMem[63] <= 8'b00000000;

        instMem[64] <= 8'b10010100; //-- st	r3,r1,4
        instMem[65] <= 8'b01100001;
        instMem[66] <= 8'b00000000;
        instMem[67] <= 8'b00000100;

        instMem[68] <= 8'b10010100; //-- st	r4,r1,8
        instMem[69] <= 8'b10000001;
        instMem[70] <= 8'b00000000;
        instMem[71] <= 8'b00001000;

        instMem[72] <= 8'b10010100; //-- st	r5,r1,12
        instMem[73] <= 8'b10100001;
        instMem[74] <= 8'b00000000;
        instMem[75] <= 8'b00001100;

        instMem[76] <= 8'b10010100; //-- st	r6,r1,16
        instMem[77] <= 8'b11000001;
        instMem[78] <= 8'b00000000;
        instMem[79] <= 8'b00010000;

        instMem[80] <= 8'b10010100; //-- st	r7,r1,20
        instMem[81] <= 8'b11100001;
        instMem[82] <= 8'b00000000;
        instMem[83] <= 8'b00010100;

        instMem[84] <= 8'b10010101; //-- st	r8,r1,24
        instMem[85] <= 8'b00000001;
        instMem[86] <= 8'b00000000;
        instMem[87] <= 8'b00011000;

        instMem[88] <= 8'b10010101; //-- st	r9,r1,28
        instMem[89] <= 8'b00100001;
        instMem[90] <= 8'b00000000;
        instMem[91] <= 8'b00011100;

        instMem[92] <= 8'b10010101; //-- st	r10,r1,32
        instMem[93] <= 8'b01000001;
        instMem[94] <= 8'b00000000;
        instMem[95] <= 8'b00100000;

        instMem[96] <= 8'b10010101; //-- st	r11,r1,36
        instMem[97] <= 8'b01100001;
        instMem[98] <= 8'b00000000;
        instMem[99] <= 8'b00100100;

        instMem[100] <= 8'b10000000; //-- Addi 	r1,r0,3
        instMem[101] <= 8'b00100000;
        instMem[102] <= 8'b00000000;
        instMem[103] <= 8'b00000011;

        instMem[104] <= 8'b10000000; //-- Addi	r4,r0,1024
        instMem[105] <= 8'b10000000;
        instMem[106] <= 8'b00000100;
        instMem[107] <= 8'b00000000;

        instMem[108] <= 8'b10000000; //-- Addi 	r2,r0,0
        instMem[109] <= 8'b01000000;
        instMem[110] <= 8'b00000000;
        instMem[111] <= 8'b00000000;

        instMem[112] <= 8'b10000000; //-- Addi 	r3,r0,1
        instMem[113] <= 8'b01100000;
        instMem[114] <= 8'b00000000;
        instMem[115] <= 8'b00000001;

        instMem[116] <= 8'b10000001; //-- Addi 	r9,r0,2
        instMem[117] <= 8'b00100000;
        instMem[118] <= 8'b00000000;
        instMem[119] <= 8'b00000010;

        instMem[120] <= 8'b00101001; //-- sll	r8,r3,r9
        instMem[121] <= 8'b00000011;
        instMem[122] <= 8'b01001000;
        instMem[123] <= 8'b00000000;

        instMem[124] <= 8'b00000101; //-- Add 	r8,r4,r8
        instMem[125] <= 8'b00000100;
        instMem[126] <= 8'b01000000;
        instMem[127] <= 8'b00000000;

        instMem[128] <= 8'b10010000; //-- ld	r5,r8,0
        instMem[129] <= 8'b10101000;
        instMem[130] <= 8'b00000000;
        instMem[131] <= 8'b00000000;

        instMem[132] <= 8'b10010000; //-- ld	r6,r8,-4
        instMem[133] <= 8'b11001000;
        instMem[134] <= 8'b11111111;
        instMem[135] <= 8'b11111100;

        instMem[136] <= 8'b00001101; //-- sub 	r9,r5,r6
        instMem[137] <= 8'b00100101;
        instMem[138] <= 8'b00110000;
        instMem[139] <= 8'b00000000;

        instMem[140] <= 8'b10000001; //-- Addi 	r10,r0,0x8000
        instMem[141] <= 8'b01000000;
        instMem[142] <= 8'b10000000;
        instMem[143] <= 8'b00000000;

        instMem[144] <= 8'b10000001; //-- Addi	r11,r0,16
        instMem[145] <= 8'b01100000;
        instMem[146] <= 8'b00000000;
        instMem[147] <= 8'b00010000;

        instMem[148] <= 8'b00101001; //-- sll	r10,r10,r11
        instMem[149] <= 8'b01001010;
        instMem[150] <= 8'b01011000;
        instMem[151] <= 8'b00000000;

        instMem[152] <= 8'b00010101; //-- And 	r9,r9,r10
        instMem[153] <= 8'b00101001;
        instMem[154] <= 8'b01010000;
        instMem[155] <= 8'b00000000;

        instMem[156] <= 8'b10100000; //-- Bez	r9,2
        instMem[157] <= 8'b00001001;
        instMem[158] <= 8'b00000000;
        instMem[159] <= 8'b00000010;

        instMem[160] <= 8'b10010100; //-- st	r5,r8,-4
        instMem[161] <= 8'b10101000;
        instMem[162] <= 8'b11111111;
        instMem[163] <= 8'b11111100;

        instMem[164] <= 8'b10010100; //-- st	r6,r8,0
        instMem[165] <= 8'b11001000;
        instMem[166] <= 8'b00000000;
        instMem[167] <= 8'b00000000;

        instMem[168] <= 8'b10000000; //-- Addi 	r3,r3,1
        instMem[169] <= 8'b01100011;
        instMem[170] <= 8'b00000000;
        instMem[171] <= 8'b00000001;

        instMem[172] <= 8'b10100100; //-- BNE	r3,r1,-15
        instMem[173] <= 8'b01100001;
        instMem[174] <= 8'b11111111;
        instMem[175] <= 8'b11110001;

        instMem[176] <= 8'b10000000; //-- Addi 	r2,r2,1
        instMem[177] <= 8'b01000010;
        instMem[178] <= 8'b00000000;
        instMem[179] <= 8'b00000001;

        instMem[180] <= 8'b10100100; //-- BNE	r2,r1,-18
        instMem[181] <= 8'b01000001;
        instMem[182] <= 8'b11111111;
        instMem[183] <= 8'b11101110;

        instMem[184] <= 8'b10000000; //-- Addi 	r1,r0,1024
        instMem[185] <= 8'b00100000;
        instMem[186] <= 8'b00000100;
        instMem[187] <= 8'b00000000;

        instMem[188] <= 8'b10010000; //-- ld	r2,r1,0
        instMem[189] <= 8'b01000001;
        instMem[190] <= 8'b00000000;
        instMem[191] <= 8'b00000000;

        instMem[192] <= 8'b10010000; //-- ld	r3,r1,4
        instMem[193] <= 8'b01100001;
        instMem[194] <= 8'b00000000;
        instMem[195] <= 8'b00000100;

        instMem[196] <= 8'b10010000; //-- ld	r4,r1,8
        instMem[197] <= 8'b10000001;
        instMem[198] <= 8'b00000000;
        instMem[199] <= 8'b00001000;

        instMem[200] <= 8'b10010000; //-- ld	r5,r1,12
        instMem[201] <= 8'b10100001;
        instMem[202] <= 8'b00000000;
        instMem[203] <= 8'b00001100;

        instMem[204] <= 8'b10010000; //-- ld	r6,r1,16
        instMem[205] <= 8'b11000001;
        instMem[206] <= 8'b00000000;
        instMem[207] <= 8'b00010000;

        instMem[208] <= 8'b10010000; //-- ld	r7,r1,20
        instMem[209] <= 8'b11100001;
        instMem[210] <= 8'b00000000;
        instMem[211] <= 8'b00010100;

        instMem[212] <= 8'b10010001; //-- ld	r8,r1,24
        instMem[213] <= 8'b00000001;
        instMem[214] <= 8'b00000000;
        instMem[215] <= 8'b00011000;

        instMem[216] <= 8'b10010001; //-- ld	r9,r1,28
        instMem[217] <= 8'b00100001;
        instMem[218] <= 8'b00000000;
        instMem[219] <= 8'b00011100;

        instMem[220] <= 8'b10010001; //-- ld	r10,r1,32
        instMem[221] <= 8'b01000001;
        instMem[222] <= 8'b00000000;
        instMem[223] <= 8'b00100000;

        instMem[224] <= 8'b10010001; //-- ld	r11,r1,36
        instMem[225] <= 8'b01100001;
        instMem[226] <= 8'b00000000;
        instMem[227] <= 8'b00100100;

        instMem[228] <= 8'b10101000; //-- JMP 	-1
        instMem[229] <= 8'b00000000;
        instMem[230] <= 8'b11111111;
        instMem[231] <= 8'b11111111;

        instMem[232] <= 8'b00000000; //-- NOPE
        instMem[233] <= 8'b00000000;
        instMem[234] <= 8'b00000000;
        instMem[235] <= 8'b00000000;
      end
    end

  assign instruction = {instMem[address], instMem[address + 1], instMem[address + 2], instMem[address + 3]};
endmodule // insttructionMem


================================================
FILE: modules/memoryModules/regFile.v
================================================
`include "defines.v"

module regFile (clk, rst, src1, src2, dest, writeVal, writeEn, reg1, reg2);
  input clk, rst, writeEn;
  input [`REG_FILE_ADDR_LEN-1:0] src1, src2, dest;
  input [`WORD_LEN-1:0] writeVal;
  output [`WORD_LEN-1:0] reg1, reg2;

  reg [`WORD_LEN-1:0] regMem [0:`REG_FILE_SIZE-1];
  integer i;

  always @ (negedge clk) begin
    if (rst) begin
      for (i = 0; i < `WORD_LEN; i = i + 1)
        regMem[i] <= 0;
	    end

    else if (writeEn) regMem[dest] <= writeVal;
    regMem[0] <= 0;
  end

  assign reg1 = (regMem[src1]);
  assign reg2 = (regMem[src2]);
endmodule // regFile


================================================
FILE: modules/mux.v
================================================
`include "defines.v"

module mux #(parameter integer LENGTH) (in1, in2, sel, out);
  input sel;
  input [LENGTH-1:0] in1, in2;
  output [LENGTH-1:0] out;

  assign out = (sel == 0) ? in1 : in2;
endmodule // mxu

module mux_3input #(parameter integer LENGTH) (in1, in2, in3, sel, out);
  input [LENGTH-1:0] in1, in2, in3;
  input [1:0] sel;
  output [LENGTH-1:0] out;

  assign out = (sel == 2'd0) ? in1 :
               (sel == 2'd1) ? in2 : in3;
endmodule // mux


================================================
FILE: modules/pipeRegisters/EXE2MEM.v
================================================
`include "defines.v"

module EXE2MEM (clk, rst, WB_EN_IN, MEM_R_EN_IN, MEM_W_EN_IN, PCIn, ALUResIn, STValIn, destIn,
                          WB_EN,    MEM_R_EN,    MEM_W_EN,    PC,   ALURes,   STVal,   dest);
  input clk, rst;
  // TO BE REGISTERED FOR ID STAGE
  input WB_EN_IN, MEM_R_EN_IN, MEM_W_EN_IN;
  input [`REG_FILE_ADDR_LEN-1:0] destIn;
  input [`WORD_LEN-1:0] PCIn, ALUResIn, STValIn;
  // REGISTERED VALUES FOR ID STAGE
  output reg WB_EN, MEM_R_EN, MEM_W_EN;
  output reg [`REG_FILE_ADDR_LEN-1:0] dest;
  output reg [`WORD_LEN-1:0] PC, ALURes, STVal;

  always @ (posedge clk) begin
    if (rst) begin
      {WB_EN, MEM_R_EN, MEM_W_EN, PC, ALURes, STVal, dest} <= 0;
    end
    else begin
      WB_EN <= WB_EN_IN;
      MEM_R_EN <= MEM_R_EN_IN;
      MEM_W_EN <= MEM_W_EN_IN;
      PC <= PCIn;
      ALURes <= ALUResIn;
      STVal <= STValIn;
      dest <= destIn;
    end
  end
endmodule // EXE2MEM


================================================
FILE: modules/pipeRegisters/ID2EXE.v
================================================
`include "defines.v"

module ID2EXE (clk, rst, destIn, reg2In, val1In, val2In, PCIn, EXE_CMD_IN, MEM_R_EN_IN, MEM_W_EN_IN, WB_EN_IN, brTaken_in, src1_in, src2_in,
                         dest,   ST_value,   val1,   val2,   PC,  EXE_CMD,    MEM_R_EN,    MEM_W_EN,    WB_EN, brTaken_out, src1_out, src2_out);
  input clk, rst;
  // TO BE REGISTERED FOR ID STAGE
  input MEM_R_EN_IN, MEM_W_EN_IN, WB_EN_IN, brTaken_in;
  input [`EXE_CMD_LEN-1:0] EXE_CMD_IN;
  input [`REG_FILE_ADDR_LEN-1:0] destIn, src1_in, src2_in;
  input [`WORD_LEN-1:0] reg2In, val1In, val2In, PCIn;
  // REGISTERED VALUES FOR ID STAGE
  output reg MEM_R_EN, MEM_W_EN, WB_EN, brTaken_out;
  output reg [`EXE_CMD_LEN-1:0] EXE_CMD;
  output reg [`REG_FILE_ADDR_LEN-1:0] dest, src1_out, src2_out;
  output reg [`WORD_LEN-1:0] ST_value, val1, val2, PC;

  always @ (posedge clk) begin
    if (rst) begin
      {MEM_R_EN, MEM_R_EN, WB_EN, EXE_CMD, dest, ST_value, val1, val2, PC, brTaken_out, src1_out, src2_out} <= 0;
    end
    else begin
      MEM_R_EN <= MEM_R_EN_IN;
      MEM_W_EN <= MEM_W_EN_IN;
      WB_EN <= WB_EN_IN;
      EXE_CMD <= EXE_CMD_IN;
      dest <= destIn;
      ST_value <= reg2In;
      val1 <= val1In;
      val2 <= val2In;
      PC <= PCIn;
      brTaken_out <= brTaken_in;
      src1_out <= src1_in;
      src2_out <= src2_in;
    end
  end
endmodule // ID2EXE


================================================
FILE: modules/pipeRegisters/IF2ID.v
================================================
`include "defines.v"

module IF2ID (clk, rst, flush, freeze, PCIn, instructionIn, PC, instruction);
  input clk, rst, flush, freeze;
  input [`WORD_LEN-1:0] PCIn, instructionIn;
  output reg [`WORD_LEN-1:0] PC, instruction;

  always @ (posedge clk) begin
    if (rst) begin
      PC <= 0;
      instruction <= 0;
    end
    else begin
      if (~freeze) begin
        if (flush) begin
          instruction <= 0;
          PC <= 0;
        end
        else begin
          instruction <= instructionIn;
          PC <= PCIn;
        end
      end
    end
  end
endmodule // IF2ID


================================================
FILE: modules/pipeRegisters/MEM2WB.v
================================================
`include "defines.v"

module MEM2WB (clk, rst, WB_EN_IN, MEM_R_EN_IN, ALUResIn, memReadValIn, destIn,
                         WB_EN,    MEM_R_EN,    ALURes,   memReadVal,   dest);
  input clk, rst;
  // TO BE REGISTERED FOR ID STAGE
  input WB_EN_IN, MEM_R_EN_IN;
  input [`REG_FILE_ADDR_LEN-1:0] destIn;
  input [`WORD_LEN-1:0] ALUResIn, memReadValIn;
  // REGISTERED VALUES FOR ID STAGE
  output reg WB_EN, MEM_R_EN;
  output reg [`REG_FILE_ADDR_LEN-1:0] dest;
  output reg [`WORD_LEN-1:0] ALURes, memReadVal;

  always @ (posedge clk) begin
    if (rst) begin
      {WB_EN, MEM_R_EN, dest, ALURes, memReadVal} <= 0;
    end
    else begin
      WB_EN <= WB_EN_IN;
      MEM_R_EN <= MEM_R_EN_IN;
      dest <= destIn;
      ALURes <= ALUResIn;
      memReadVal <= memReadValIn;
    end
  end
endmodule // MEM2WB


================================================
FILE: modules/pipeStages/EXEStage.v
================================================
`include "defines.v"

module EXEStage (clk, EXE_CMD, val1_sel, val2_sel, ST_val_sel, val1, val2, ALU_res_MEM, result_WB, ST_value_in, ALUResult, ST_value_out);
  input clk;
  input [`FORW_SEL_LEN-1:0] val1_sel, val2_sel, ST_val_sel;
  input [`EXE_CMD_LEN-1:0] EXE_CMD;
  input [`WORD_LEN-1:0] val1, val2, ALU_res_MEM, result_WB, ST_value_in;
  output [`WORD_LEN-1:0] ALUResult, ST_value_out;

  wire [`WORD_LEN-1:0] ALU_val1, ALU_val2;

  mux_3input #(.LENGTH(`WORD_LEN)) mux_val1 (
    .in1(val1),
    .in2(ALU_res_MEM),
    .in3(result_WB),
    .sel(val1_sel),
    .out(ALU_val1)
  );

  mux_3input #(.LENGTH(`WORD_LEN)) mux_val2 (
    .in1(val2),
    .in2(ALU_res_MEM),
    .in3(result_WB),
    .sel(val2_sel),
    .out(ALU_val2)
  );

  mux_3input #(.LENGTH(`WORD_LEN)) mux_ST_value (
    .in1(ST_value_in),
    .in2(ALU_res_MEM),
    .in3(result_WB),
    .sel(ST_val_sel),
    .out(ST_value_out)
  );

  ALU ALU(
    .val1(ALU_val1),
    .val2(ALU_val2),
    .EXE_CMD(EXE_CMD),
    .aluOut(ALUResult)
  );
endmodule // EXEStage


================================================
FILE: modules/pipeStages/IDStage.v
================================================
`include "defines.v"

module IDStage (clk, rst, hazard_detected_in, is_imm_out, ST_or_BNE_out, instruction, reg1, reg2, src1, src2_reg_file, src2_forw, val1, val2, brTaken, EXE_CMD, MEM_R_EN, MEM_W_EN, WB_EN, branch_comm);
  input clk, rst, hazard_detected_in;
  input [`WORD_LEN-1:0] instruction, reg1, reg2;
  output brTaken, MEM_R_EN, MEM_W_EN, WB_EN, is_imm_out, ST_or_BNE_out;
  output [1:0] branch_comm;
  output [`EXE_CMD_LEN-1:0] EXE_CMD;
  output [`REG_FILE_ADDR_LEN-1:0] src1, src2_reg_file, src2_forw;
  output [`WORD_LEN-1:0] val1, val2;

  wire CU2and, Cond2and;
  wire [1:0] CU2Cond;
  wire Is_Imm, ST_or_BNE;
  wire [`WORD_LEN-1:0] signExt2Mux;

  controller controller(
    // INPUT
    .opCode(instruction[31:26]),
    .branchEn(CU2and),
    // OUTPUT
    .EXE_CMD(EXE_CMD),
    .Branch_command(CU2Cond),
    .Is_Imm(Is_Imm),
    .ST_or_BNE(ST_or_BNE),
    .WB_EN(WB_EN),
    .MEM_R_EN(MEM_R_EN),
    .MEM_W_EN(MEM_W_EN),
    .hazard_detected(hazard_detected_in)
  );

  mux #(.LENGTH(`REG_FILE_ADDR_LEN)) mux_src2 ( // determins the register source 2 for register file
    .in1(instruction[15:11]),
    .in2(instruction[25:21]),
    .sel(ST_or_BNE),
    .out(src2_reg_file)
  );

  mux #(.LENGTH(`WORD_LEN)) mux_val2 ( // determins whether val2 is from the reg file or the immediate value
    .in1(reg2),
    .in2(signExt2Mux),
    .sel(Is_Imm),
    .out(val2)
  );

  mux #(.LENGTH(`REG_FILE_ADDR_LEN)) mux_src2_forw ( // determins the value of register source 2 for forwarding
    .in1(instruction[15:11]), // src2 = instruction[15:11]
    .in2(5'd0),
    .sel(Is_Imm),
    .out(src2_forw)
  );

  signExtend signExtend(
    .in(instruction[15:0]),
    .out(signExt2Mux)
  );

  conditionChecker conditionChecker (
    .reg1(reg1),
    .reg2(reg2),
    .cuBranchComm(CU2Cond),
    .brCond(Cond2and)
  );

  assign brTaken = CU2and && Cond2and;
  assign val1 = reg1;
  assign src1 = instruction[20:16];
  assign is_imm_out = Is_Imm;
  assign ST_or_BNE_out = ST_or_BNE;
  assign branch_comm = CU2Cond;
endmodule // IDStage


================================================
FILE: modules/pipeStages/IFStage.v
================================================
`include "defines.v"

module IFStage (clk, rst, brTaken, brOffset, freeze, PC, instruction);
  input clk, rst, brTaken, freeze;
  input [`WORD_LEN-1:0] brOffset;
  output [`WORD_LEN-1:0] PC, instruction;

  wire [`WORD_LEN-1:0] adderIn1, adderOut, brOffserTimes4;

  mux #(.LENGTH(`WORD_LEN)) adderInput (
    .in1(32'd4),
    .in2(brOffserTimes4),
    .sel(brTaken),
    .out(adderIn1)
  );

  adder add4 (
    .in1(adderIn1),
    .in2(PC),
    .out(adderOut)
  );

  register PCReg (
    .clk(clk),
    .rst(rst),
    .writeEn(~freeze),
    .regIn(adderOut),
    .regOut(PC)
  );

  instructionMem instructions (
    .rst(rst),
    .addr(PC),
    .instruction(instruction)
  );

  assign brOffserTimes4 = brOffset << 2;
endmodule // IFStage


================================================
FILE: modules/pipeStages/MEMStage.v
================================================
`include "defines.v"

module MEMStage (clk, rst, MEM_R_EN, MEM_W_EN, ALU_res, ST_value, dataMem_out);
  input clk, rst, MEM_R_EN, MEM_W_EN;
  input [`WORD_LEN-1:0] ALU_res, ST_value;
  output [`WORD_LEN-1:0]  dataMem_out;

  dataMem dataMem (
    .clk(clk),
    .rst(rst),
    .writeEn(MEM_W_EN),
    .readEn(MEM_R_EN),
    .address(ALU_res),
    .dataIn(ST_value),
    .dataOut(dataMem_out)
  );
endmodule // MEMStage


================================================
FILE: modules/pipeStages/WBStage.v
================================================
`include "defines.v"

module WBStage (MEM_R_EN, memData, aluRes, WB_res);
  input MEM_R_EN;
  input [`WORD_LEN-1:0] memData, aluRes;
  output [`WORD_LEN-1:0] WB_res;

  assign WB_res = (MEM_R_EN) ? memData : aluRes;
endmodule // WBStage


================================================
FILE: modules/register.v
================================================
`include "defines.v"

module register (clk, rst, writeEn, regIn, regOut);
  input clk, rst, writeEn;
  input [`WORD_LEN-1:0] regIn;
  output reg [`WORD_LEN-1:0] regOut;

  always @ (posedge clk) begin
    if (rst == 1) regOut <= 0;
    else if (writeEn) regOut <= regIn;
  end
endmodule // register


================================================
FILE: modules/signExtend.v
================================================
`include "defines.v"

module signExtend (in, out);
  input [15:0] in;
  output [`WORD_LEN-1:0] out;

  assign out = (in[15] == 1) ? {16'b1111111111111111, in} : {16'b0000000000000000, in};
endmodule // signExtend


================================================
FILE: testbench.v
================================================
`timescale 1ns/1ns

module testbench ();
  reg clk,rst, forwarding_EN;
  MIPS_Processor top_module (clk, rst, forwarding_EN);

  initial begin
    clk=1;
    repeat(5000) #50 clk=~clk ;
  end

  initial begin
    rst = 1;
    forwarding_EN = 0;
    #100
    rst = 0;
  end
endmodule // test


================================================
FILE: topLevelCircuit.v
================================================
`include "defines.v"

module MIPS_Processor (input CLOCK_50, input rst, input forward_EN);
	wire clock = CLOCK_50;
	wire [`WORD_LEN-1:0] PC_IF, PC_ID, PC_EXE, PC_MEM;
	wire [`WORD_LEN-1:0] inst_IF, inst_ID;
	wire [`WORD_LEN-1:0] reg1_ID, reg2_ID, ST_value_EXE, ST_value_EXE2MEM, ST_value_MEM;
	wire [`WORD_LEN-1:0] val1_ID, val1_EXE;
	wire [`WORD_LEN-1:0] val2_ID, val2_EXE;
	wire [`WORD_LEN-1:0] ALURes_EXE, ALURes_MEM, ALURes_WB;
	wire [`WORD_LEN-1:0] dataMem_out_MEM, dataMem_out_WB;
	wire [`WORD_LEN-1:0] WB_result;
	wire [`REG_FILE_ADDR_LEN-1:0] dest_EXE, dest_MEM, dest_WB; // dest_ID = instruction[25:21] thus nothing declared
	wire [`REG_FILE_ADDR_LEN-1:0] src1_ID, src2_regFile_ID, src2_forw_ID, src2_forw_EXE, src1_forw_EXE;
	wire [`EXE_CMD_LEN-1:0] EXE_CMD_ID, EXE_CMD_EXE;
	wire [`FORW_SEL_LEN-1:0] val1_sel, val2_sel, ST_val_sel;
	wire [1:0] branch_comm;
	wire Br_Taken_ID, IF_Flush, Br_Taken_EXE;
	wire MEM_R_EN_ID, MEM_R_EN_EXE, MEM_R_EN_MEM, MEM_R_EN_WB;
	wire MEM_W_EN_ID, MEM_W_EN_EXE, MEM_W_EN_MEM;
	wire WB_EN_ID, WB_EN_EXE, WB_EN_MEM, WB_EN_WB;
	wire hazard_detected, is_imm, ST_or_BNE;

	regFile regFile(
		// INPUTS
		.clk(clock),
		.rst(rst),
		.src1(src1_ID),
		.src2(src2_regFile_ID),
		.dest(dest_WB),
		.writeVal(WB_result),
		.writeEn(WB_EN_WB),
		// OUTPUTS
		.reg1(reg1_ID),
		.reg2(reg2_ID)
	);

	hazard_detection hazard (
		// INPUTS
		.forward_EN(forward_EN),
		.is_imm(is_imm),
		.ST_or_BNE(ST_or_BNE),
		.src1_ID(src1_ID),
		.src2_ID(src2_regFile_ID),
		.dest_EXE(dest_EXE),
		.dest_MEM(dest_MEM),
		.WB_EN_EXE(WB_EN_EXE),
		.WB_EN_MEM(WB_EN_MEM),
		.MEM_R_EN_EXE(MEM_R_EN_EXE),
		// OUTPUTS
		.branch_comm(branch_comm),
		.hazard_detected(hazard_detected)
	);

	forwarding_EXE forwrding_EXE (
		.src1_EXE(src1_forw_EXE),
		.src2_EXE(src2_forw_EXE),
		.ST_src_EXE(dest_EXE),
		.dest_MEM(dest_MEM),
		.dest_WB(dest_WB),
		.WB_EN_MEM(WB_EN_MEM),
		.WB_EN_WB(WB_EN_WB),
		.val1_sel(val1_sel),
		.val2_sel(val2_sel),
		.ST_val_sel(ST_val_sel)
	);

	//###########################
	//##### PIPLINE STAGES ######
	//###########################
	IFStage IFStage (
		// INPUTS
		.clk(clock),
		.rst(rst),
		.freeze(hazard_detected),
		.brTaken(Br_Taken_ID),
		.brOffset(val2_ID),
		// OUTPUTS
		.instruction(inst_IF),
		.PC(PC_IF)
	);

	IDStage IDStage (
		// INPUTS
		.clk(clock),
		.rst(rst),
		.hazard_detected_in(hazard_detected),
		.instruction(inst_ID),
		.reg1(reg1_ID),
		.reg2(reg2_ID),
		// OUTPUTS
		.src1(src1_ID),
		.src2_reg_file(src2_regFile_ID),
		.src2_forw(src2_forw_ID),
		.val1(val1_ID),
		.val2(val2_ID),
		.brTaken(Br_Taken_ID),
		.EXE_CMD(EXE_CMD_ID),
		.MEM_R_EN(MEM_R_EN_ID),
		.MEM_W_EN(MEM_W_EN_ID),
		.WB_EN(WB_EN_ID),
		.is_imm_out(is_imm),
		.ST_or_BNE_out(ST_or_BNE),
		.branch_comm(branch_comm)
	);

	EXEStage EXEStage (
		// INPUTS
		.clk(clock),
		.EXE_CMD(EXE_CMD_EXE),
		.val1_sel(val1_sel),
		.val2_sel(val2_sel),
		.ST_val_sel(ST_val_sel),
		.val1(val1_EXE),
		.val2(val2_EXE),
		.ALU_res_MEM(ALURes_MEM),
		.result_WB(WB_result),
		.ST_value_in(ST_value_EXE),
		// OUTPUTS
		.ALUResult(ALURes_EXE),
		.ST_value_out(ST_value_EXE2MEM)
	);

	MEMStage MEMStage (
		// INPUTS
		.clk(clock),
		.rst(rst),
		.MEM_R_EN(MEM_R_EN_MEM),
		.MEM_W_EN(MEM_W_EN_MEM),
		.ALU_res(ALURes_MEM),
		.ST_value(ST_value_MEM),
		// OUTPUTS
		.dataMem_out(dataMem_out_MEM)
	);

	WBStage WBStage (
		// INPUTS
		.MEM_R_EN(MEM_R_EN_WB),
		.memData(dataMem_out_WB),
		.aluRes(ALURes_WB),
		// OUTPUTS
		.WB_res(WB_result)
	);

	//############################
	//#### PIPLINE REGISTERS #####
	//############################
	IF2ID IF2IDReg (
		// INPUTS
		.clk(clock),
		.rst(rst),
		.flush(IF_Flush),
		.freeze(hazard_detected),
		.PCIn(PC_IF),
		.instructionIn(inst_IF),
		// OUTPUTS
		.PC(PC_ID),
		.instruction(inst_ID)
	);

	ID2EXE ID2EXEReg (
		.clk(clock),
		.rst(rst),
		// INPUTS
		.destIn(inst_ID[25:21]),
		.src1_in(src1_ID),
		.src2_in(src2_forw_ID),
		.reg2In(reg2_ID),
		.val1In(val1_ID),
		.val2In(val2_ID),
		.PCIn(PC_ID),
		.EXE_CMD_IN(EXE_CMD_ID),
		.MEM_R_EN_IN(MEM_R_EN_ID),
		.MEM_W_EN_IN(MEM_W_EN_ID),
		.WB_EN_IN(WB_EN_ID),
		.brTaken_in(Br_Taken_ID),
		// OUTPUTS
		.src1_out(src1_forw_EXE),
		.src2_out(src2_forw_EXE),
		.dest(dest_EXE),
		.ST_value(ST_value_EXE),
		.val1(val1_EXE),
		.val2(val2_EXE),
		.PC(PC_EXE),
		.EXE_CMD(EXE_CMD_EXE),
		.MEM_R_EN(MEM_R_EN_EXE),
		.MEM_W_EN(MEM_W_EN_EXE),
		.WB_EN(WB_EN_EXE),
		.brTaken_out(Br_Taken_EXE)
	);

	EXE2MEM EXE2MEMReg (
		.clk(clock),
		.rst(rst),
		// INPUTS
		.WB_EN_IN(WB_EN_EXE),
		.MEM_R_EN_IN(MEM_R_EN_EXE),
		.MEM_W_EN_IN(MEM_W_EN_EXE),
		.PCIn(PC_EXE),
		.ALUResIn(ALURes_EXE),
		.STValIn(ST_value_EXE2MEM),
		.destIn(dest_EXE),
		// OUTPUTS
		.WB_EN(WB_EN_MEM),
		.MEM_R_EN(MEM_R_EN_MEM),
		.MEM_W_EN(MEM_W_EN_MEM),
		.PC(PC_MEM),
		.ALURes(ALURes_MEM),
		.STVal(ST_value_MEM),
		.dest(dest_MEM)
	);

	MEM2WB MEM2WB(
		.clk(clock),
		.rst(rst),
		// INPUTS
		.WB_EN_IN(WB_EN_MEM),
		.MEM_R_EN_IN(MEM_R_EN_MEM),
		.ALUResIn(ALURes_MEM),
		.memReadValIn(dataMem_out_MEM),
		.destIn(dest_MEM),
		// OUTPUTS
		.WB_EN(WB_EN_WB),
		.MEM_R_EN(MEM_R_EN_WB),
		.ALURes(ALURes_WB),
		.memReadVal(dataMem_out_WB),
		.dest(dest_WB)
	);

	assign IF_Flush = Br_Taken_ID;
endmodule
Download .txt
gitextract_pppgpag3/

├── .gitignore
├── README.md
├── alteraDE2SimulationFiles/
│   ├── 7segConv.v
│   └── DE2_TOP.V
├── defines.v
├── instructions/
│   ├── example_source_code.txt
│   └── rearrange_instructions.py
├── modules/
│   ├── ALU.v
│   ├── adder.v
│   ├── controlUnit/
│   │   ├── conditionChecker.v
│   │   └── controller.v
│   ├── hazard_forwarding/
│   │   ├── forwarding.v
│   │   └── hazardDetection.v
│   ├── memoryModules/
│   │   ├── dataMem.v
│   │   ├── instructionMem.v
│   │   └── regFile.v
│   ├── mux.v
│   ├── pipeRegisters/
│   │   ├── EXE2MEM.v
│   │   ├── ID2EXE.v
│   │   ├── IF2ID.v
│   │   └── MEM2WB.v
│   ├── pipeStages/
│   │   ├── EXEStage.v
│   │   ├── IDStage.v
│   │   ├── IFStage.v
│   │   ├── MEMStage.v
│   │   └── WBStage.v
│   ├── register.v
│   └── signExtend.v
├── testbench.v
└── topLevelCircuit.v
Condensed preview — 30 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (66K chars).
[
  {
    "path": ".gitignore",
    "chars": 155,
    "preview": "*.csv\n*.mpf\n*.qpf\n*.qsf\n*.v.bak\n*.wlf\n*.cr.mti\n.DS_Store\n\nconfigs/\ndb/\nincremental_db/\noutput_files/\nsimulation/\nwork/\ni"
  },
  {
    "path": "README.md",
    "chars": 3643,
    "preview": "# MIPS-pipeline-processor\n\nThanks for visiting this repository!\n\nDeveloped during the Fall 2017 Computer Architecture La"
  },
  {
    "path": "alteraDE2SimulationFiles/7segConv.v",
    "chars": 1181,
    "preview": "module sevenSegConv (num, out1, out2);\n  input [31:0] num;\n  output [6:0] out1, out2;\n\n  wire [31:0] numLower = num / 10"
  },
  {
    "path": "alteraDE2SimulationFiles/DE2_TOP.V",
    "chars": 16597,
    "preview": "module DE2_TOP\n\t(\n\t\t////////////////////\tClock Input\t \t////////////////////\n\t\tCLOCK_27,\t\t\t\t\t\t//\t27 MHz\n\t\tCLOCK_50,\t\t\t\t\t\t"
  },
  {
    "path": "defines.v",
    "chars": 1196,
    "preview": "// Wire widths\n`define WORD_LEN 32\n`define REG_FILE_ADDR_LEN 5\n`define EXE_CMD_LEN 4\n`define FORW_SEL_LEN 2\n`define OP_C"
  },
  {
    "path": "instructions/example_source_code.txt",
    "chars": 3488,
    "preview": "10000000001000000000000000001010; Addi r1,r0,10\t\t*** (1 begins) performing basic arithmetic operations\n00000100010000000"
  },
  {
    "path": "instructions/rearrange_instructions.py",
    "chars": 1436,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n# Rearranging instructions from a source file to a format suitable for th"
  },
  {
    "path": "modules/ALU.v",
    "chars": 677,
    "preview": "`include \"defines.v\"\n\nmodule ALU (val1, val2, EXE_CMD, aluOut);\n  input [`WORD_LEN-1:0] val1, val2;\n  input [`EXE_CMD_LE"
  },
  {
    "path": "modules/adder.v",
    "chars": 162,
    "preview": "`include \"defines.v\"\n\nmodule adder (in1, in2, out);\n  input [`WORD_LEN-1:0] in1, in2;\n  output [`WORD_LEN-1:0] out;\n\n  a"
  },
  {
    "path": "modules/controlUnit/conditionChecker.v",
    "chars": 422,
    "preview": "`include \"defines.v\"\n\nmodule conditionChecker (reg1, reg2, cuBranchComm, brCond);\n  input [`WORD_LEN-1: 0] reg1, reg2;\n "
  },
  {
    "path": "modules/controlUnit/controller.v",
    "chars": 2338,
    "preview": "`include \"defines.v\"\n\nmodule controller (opCode, branchEn, EXE_CMD, Branch_command, Is_Imm, ST_or_BNE, WB_EN, MEM_R_EN, "
  },
  {
    "path": "modules/hazard_forwarding/forwarding.v",
    "chars": 1122,
    "preview": "`include \"defines.v\"\n\nmodule forwarding_EXE (src1_EXE, src2_EXE, ST_src_EXE, dest_MEM, dest_WB, WB_EN_MEM, WB_EN_WB, val"
  },
  {
    "path": "modules/hazard_forwarding/hazardDetection.v",
    "chars": 1038,
    "preview": "`include \"defines.v\"\n\nmodule hazard_detection(forward_EN, is_imm, ST_or_BNE, src1_ID, src2_ID, dest_EXE, WB_EN_EXE, dest"
  },
  {
    "path": "modules/memoryModules/dataMem.v",
    "chars": 835,
    "preview": "`include \"defines.v\"\n\nmodule dataMem (clk, rst, writeEn, readEn, address, dataIn, dataOut);\n  input clk, rst, readEn, wr"
  },
  {
    "path": "modules/memoryModules/instructionMem.v",
    "chars": 10313,
    "preview": "`include \"defines.v\"\n\nmodule instructionMem (rst, addr, instruction);\n  input rst;\n  input [`WORD_LEN-1:0] addr;\n  outpu"
  },
  {
    "path": "modules/memoryModules/regFile.v",
    "chars": 601,
    "preview": "`include \"defines.v\"\n\nmodule regFile (clk, rst, src1, src2, dest, writeVal, writeEn, reg1, reg2);\n  input clk, rst, writ"
  },
  {
    "path": "modules/mux.v",
    "chars": 464,
    "preview": "`include \"defines.v\"\n\nmodule mux #(parameter integer LENGTH) (in1, in2, sel, out);\n  input sel;\n  input [LENGTH-1:0] in1"
  },
  {
    "path": "modules/pipeRegisters/EXE2MEM.v",
    "chars": 917,
    "preview": "`include \"defines.v\"\n\nmodule EXE2MEM (clk, rst, WB_EN_IN, MEM_R_EN_IN, MEM_W_EN_IN, PCIn, ALUResIn, STValIn, destIn,\n   "
  },
  {
    "path": "modules/pipeRegisters/ID2EXE.v",
    "chars": 1353,
    "preview": "`include \"defines.v\"\n\nmodule ID2EXE (clk, rst, destIn, reg2In, val1In, val2In, PCIn, EXE_CMD_IN, MEM_R_EN_IN, MEM_W_EN_I"
  },
  {
    "path": "modules/pipeRegisters/IF2ID.v",
    "chars": 582,
    "preview": "`include \"defines.v\"\n\nmodule IF2ID (clk, rst, flush, freeze, PCIn, instructionIn, PC, instruction);\n  input clk, rst, fl"
  },
  {
    "path": "modules/pipeRegisters/MEM2WB.v",
    "chars": 815,
    "preview": "`include \"defines.v\"\n\nmodule MEM2WB (clk, rst, WB_EN_IN, MEM_R_EN_IN, ALUResIn, memReadValIn, destIn,\n                  "
  },
  {
    "path": "modules/pipeStages/EXEStage.v",
    "chars": 1033,
    "preview": "`include \"defines.v\"\n\nmodule EXEStage (clk, EXE_CMD, val1_sel, val2_sel, ST_val_sel, val1, val2, ALU_res_MEM, result_WB,"
  },
  {
    "path": "modules/pipeStages/IDStage.v",
    "chars": 2041,
    "preview": "`include \"defines.v\"\n\nmodule IDStage (clk, rst, hazard_detected_in, is_imm_out, ST_or_BNE_out, instruction, reg1, reg2, "
  },
  {
    "path": "modules/pipeStages/IFStage.v",
    "chars": 743,
    "preview": "`include \"defines.v\"\n\nmodule IFStage (clk, rst, brTaken, brOffset, freeze, PC, instruction);\n  input clk, rst, brTaken, "
  },
  {
    "path": "modules/pipeStages/MEMStage.v",
    "chars": 419,
    "preview": "`include \"defines.v\"\n\nmodule MEMStage (clk, rst, MEM_R_EN, MEM_W_EN, ALU_res, ST_value, dataMem_out);\n  input clk, rst, "
  },
  {
    "path": "modules/pipeStages/WBStage.v",
    "chars": 237,
    "preview": "`include \"defines.v\"\n\nmodule WBStage (MEM_R_EN, memData, aluRes, WB_res);\n  input MEM_R_EN;\n  input [`WORD_LEN-1:0] memD"
  },
  {
    "path": "modules/register.v",
    "chars": 299,
    "preview": "`include \"defines.v\"\n\nmodule register (clk, rst, writeEn, regIn, regOut);\n  input clk, rst, writeEn;\n  input [`WORD_LEN-"
  },
  {
    "path": "modules/signExtend.v",
    "chars": 213,
    "preview": "`include \"defines.v\"\n\nmodule signExtend (in, out);\n  input [15:0] in;\n  output [`WORD_LEN-1:0] out;\n\n  assign out = (in["
  },
  {
    "path": "testbench.v",
    "chars": 291,
    "preview": "`timescale 1ns/1ns\n\nmodule testbench ();\n  reg clk,rst, forwarding_EN;\n  MIPS_Processor top_module (clk, rst, forwarding"
  },
  {
    "path": "topLevelCircuit.v",
    "chars": 5193,
    "preview": "`include \"defines.v\"\n\nmodule MIPS_Processor (input CLOCK_50, input rst, input forward_EN);\n\twire clock = CLOCK_50;\n\twire"
  }
]

About this extraction

This page contains the full source code of the mhyousefi/MIPS-pipeline-processor GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 30 files (58.4 KB), approximately 22.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!