三级流水risc-v

defines

// I type inst
`define INST_TYPE_I 7'b0010011
`define INST_ADDI   3'b000
`define INST_SLTI   3'b010
`define INST_SLTIU  3'b011
`define INST_XORI   3'b100
`define INST_ORI    3'b110
`define INST_ANDI   3'b111
`define INST_SLLI   3'b001
`define INST_SRI    3'b101

// L type inst
`define INST_TYPE_L 7'b0000011
`define INST_LB     3'b000
`define INST_LH     3'b001
`define INST_LW     3'b010
`define INST_LBU    3'b100
`define INST_LHU    3'b101

// S type inst
`define INST_TYPE_S 7'b0100011
`define INST_SB     3'b000
`define INST_SH     3'b001
`define INST_SW     3'b010

// R and M type inst
`define INST_TYPE_R_M 7'b0110011
// R type inst
`define INST_ADD_SUB 3'b000
`define INST_SLL    3'b001
`define INST_SLT    3'b010
`define INST_SLTU   3'b011
`define INST_XOR    3'b100
`define INST_SR     3'b101
`define INST_OR     3'b110
`define INST_AND    3'b111
// M type inst
`define INST_MUL    3'b000
`define INST_MULH   3'b001
`define INST_MULHSU 3'b010
`define INST_MULHU  3'b011
`define INST_DIV    3'b100
`define INST_DIVU   3'b101
`define INST_REM    3'b110
`define INST_REMU   3'b111

// J type inst
`define INST_JAL    7'b1101111
`define INST_JALR   7'b1100111

`define INST_LUI    7'b0110111
`define INST_AUIPC  7'b0010111
`define INST_NOP    32'h00000013
`define INST_NOP_OP 7'b0000001
`define INST_MRET   32'h30200073
`define INST_RET    32'h00008067

`define INST_FENCE  7'b0001111
`define INST_ECALL  32'h73
`define INST_EBREAK 32'h00100073

// J type inst
`define INST_TYPE_B 7'b1100011
`define INST_BEQ    3'b000
`define INST_BNE    3'b001
`define INST_BLT    3'b100
`define INST_BGE    3'b101
`define INST_BLTU   3'b110
`define INST_BGEU   3'b111

id


`include "defines.v"

module id(
	//from if_id
	input wire[31:0] inst_i,
	input wire[31:0] inst_addr_i,
		
	// to regs 
	output reg[4:0] rs1_addr_o,
	output reg[4:0] rs2_addr_o,
	// from regs
	input wire[31:0] rs1_data_i,
	input wire[31:0] rs2_data_i,
	
	//to id_ex
	output reg[31:0] inst_o,
	output reg[31:0] inst_addr_o,
	output reg[31:0] op1_o,	
	output reg[31:0] op2_o,
	output reg[4:0]  rd_addr_o,	
	output reg 		 reg_wen
);

	wire[6:0] opcode; 
	wire[4:0] rd; 
	wire[2:0] func3; 
	wire[4:0] rs1;
	wire[4:0] rs2;
	wire[6:0] func7;
	wire[11:0]imm;
	
	assign opcode = inst_i[6:0];
	assign rd 	  = inst_i[11:7];
	assign func3  = inst_i[14:12];
	assign rs1 	  = inst_i[19:15];
	assign rs2 	  = inst_i[24:20];
	assign func7  = inst_i[31:25];
	assign imm    = inst_i[31:20];
	

	
	
	
	always @(*)begin
		inst_o  	= inst_i;
		inst_addr_o = inst_addr_i;  //写反了
		
		case(opcode)
			`INST_TYPE_I:begin
				case(func3)
					`INST_ADDI:begin
						rs1_addr_o = rs1;
						rs2_addr_o = 5'b0;
						op1_o 	   = rs1_data_i;
						op2_o      = {{20{imm[11]}},imm};
						rd_addr_o  = rd;
						reg_wen    = 1'b1;
					end
					default:begin
						rs1_addr_o = 5'b0;
						rs2_addr_o = 5'b0;
						op1_o 	   = 32'b0;
						op2_o      = 32'b0;
						rd_addr_o  = 5'b0;
						reg_wen    = 1'b0;						
					end
				endcase	
			end
			`INST_TYPE_R_M:begin
				case(func3)
					`INST_ADD_SUB:begin
						rs1_addr_o = rs1;
						rs2_addr_o = rs2;
						op1_o 	   = rs1_data_i;
						op2_o      = rs2_data_i;
						rd_addr_o  = rd;
						reg_wen    = 1'b1;
					end
					default:begin
						rs1_addr_o = 5'b0;
						rs2_addr_o = 5'b0;
						op1_o 	   = 32'b0;
						op2_o      = 32'b0;
						rd_addr_o  = 5'b0;
						reg_wen    = 1'b0;						
					end
				endcase				
			end
			
			default:begin
						rs1_addr_o = 5'b0;
						rs2_addr_o = 5'b0;
						op1_o 	   = 32'b0;
						op2_o      = 32'b0;
						rd_addr_o  = 5'b0;
						reg_wen    = 1'b0;				
			end
		endcase
	end

	


endmodule

pc_reg

module pc_reg(
	input wire 		 clk,
	input wire 		 rst,
	output reg[31:0] pc_o
);

	always @(posedge clk) begin
		if(rst == 1'b0)
			pc_o <=32'b0;
		else
			pc_o <= pc_o + 3'd4;
	end




endmodule

 id_ex

`include "defines.v"

module id_ex(
	input wire clk,
	input wire rst,
	//from id
	input wire[31:0] inst_i,
	input wire[31:0] inst_addr_i,
	input wire[31:0] op1_i,	
	input wire[31:0] op2_i,
	input wire[4:0]  rd_addr_i,	
	input wire 		 reg_wen_i,
	//to ex
	output wire[31:0] inst_o,
	output wire[31:0] inst_addr_o,
	output wire[31:0] op1_o,	
	output wire[31:0] op2_o,
	output wire[4:0]  rd_addr_o,	
	output wire 	  reg_wen_o		
);

	dff_set #(32) dff1(clk,rst,`INST_NOP,inst_i,inst_o);
	
	dff_set #(32) dff2(clk,rst,32'b0,inst_addr_i,inst_addr_o);
	
	dff_set #(32) dff3(clk,rst,32'b0,op1_i,op1_o);
	
	dff_set #(32) dff4(clk,rst,32'b0,op2_i,op2_o);
	
	dff_set #(5) dff5(clk,rst,5'b0,rd_addr_i,rd_addr_o);
	
	dff_set #(1) dff6(clk,rst,1'b0,reg_wen_i,reg_wen_o);





endmodule

if-id

`include "defines.v"

module if_id(
	input wire clk,
	input wire rst,
	input wire [31:0]  inst_i, 
	input wire [31:0]  inst_addr_i,
	output wire[31:0]  inst_addr_o, 
	output wire[31:0]  inst_o
);

	dff_set #(32) dff1(clk,rst,`INST_NOP,inst_i,inst_o);
	
	dff_set #(32) dff2(clk,rst,32'b0,inst_addr_i,inst_addr_o);



endmodule

if

module ifetch(
	//from pc
	input  wire[31:0] pc_addr_i,
	//from rom 
	input  wire[31:0] rom_inst_i,
	//to rom
	output wire[31:0] if2rom_addr_o, 
	// to if_id
	output wire[31:0] inst_addr_o, 
	output wire[31:0] inst_o
	);


	assign if2rom_addr_o = pc_addr_i;
	
	assign inst_addr_o  = pc_addr_i;
	
	assign inst_o = rom_inst_i;



endmodule

open_risc

module open_risc_v(
	input  wire 		  clk   		,
	input  wire 		  rst		    , 
	input  wire [31:0]    inst_i		,
	output wire [31:0]    inst_addr_o
);
	//pc to if
	wire[31:0] pc_reg_pc_o;
	
	//if to if_id
	wire[31:0] if_inst_addr_o;
	wire[31:0] if_inst_o;	
	
	// if_id to id
	wire[31:0] if_id_inst_addr_o;
	wire[31:0] if_id_inst_o;	
	
	//ex to regs
	wire[4:0]  ex_rd_addr_o;
	wire[31:0] ex_rd_data_o;
	wire       ex_reg_wen_o;

	//id to regs
	wire[4:0] id_rs1_addr_o;
	wire[4:0] id_rs2_addr_o;
	
	//id to id_ex
	wire[31:0] id_inst_o;
	wire[31:0] id_inst_addr_o;
	wire[31:0] id_op1_o;
	wire[31:0] id_op2_o;
	wire[4:0]  id_rd_addr_o;
	wire       id_reg_wen;

	//regs to id
	wire[31:0] regs_reg1_rdata_o;
	wire[31:0] regs_reg2_rdata_o;
	
	
	//id_ex to ex
	wire[31:0] id_ex_inst_o;
	wire[31:0] id_ex_inst_addr_o;
	wire[31:0] id_ex_op1_o;
	wire[31:0] id_ex_op2_o;
	wire[4:0]  id_ex_rd_addr_o;
	wire       id_ex_reg_wen;
	
	pc_reg pc_reg_inst(
		.clk	(clk),
		.rst	(rst),
		.pc_o   (pc_reg_pc_o)
	);
	
	
	ifetch ifetch_inst(
		.pc_addr_i		(pc_reg_pc_o),
		.rom_inst_i		(inst_i),
		.if2rom_addr_o	(inst_addr_o), 
		.inst_addr_o	(if_inst_addr_o), 
		.inst_o         (if_inst_o)
	);


	if_id if_id_inst(
		.clk			(clk		      ),
		.rst			(rst		      ),	
		.inst_i			(if_inst_o        ),  
		.inst_addr_i	(if_inst_addr_o   ),  
		.inst_addr_o	(if_id_inst_addr_o), 
		.inst_o         (if_id_inst_o	  )
	);
	

	
	id id_inst(
		.inst_i			(if_id_inst_o),
		.inst_addr_i	(if_id_inst_addr_o),
		.rs1_addr_o		(id_rs1_addr_o),
		.rs2_addr_o		(id_rs2_addr_o),
		.rs1_data_i		(regs_reg1_rdata_o),
		.rs2_data_i		(regs_reg2_rdata_o),
		.inst_o			(id_inst_o),
		.inst_addr_o	(id_inst_addr_o),	
		.op1_o			(id_op1_o),	
		.op2_o			(id_op2_o),
		.rd_addr_o		(id_rd_addr_o),	
		.reg_wen        (id_reg_wen)
		);


	
	regs regs_inst(
		.clk			(clk),
		.rst			(rst),
		.reg1_raddr_i	(id_rs1_addr_o),
		.reg2_raddr_i	(id_rs2_addr_o), 
		.reg1_rdata_o	(regs_reg1_rdata_o),
		.reg2_rdata_o	(regs_reg2_rdata_o),
		.reg_waddr_i	(ex_rd_addr_o),
		.reg_wdata_i	(ex_rd_data_o),
		.reg_wen        (ex_reg_wen_o)
	);
	

	id_ex id_ex_inst(
		.clk			(clk),
		.rst			(rst),
		.inst_i			(id_inst_o),
		.inst_addr_i	(id_inst_addr_o),
		.op1_i			(id_op1_o),	
		.op2_i			(id_op2_o),
		.rd_addr_i		(id_rd_addr_o),	
		.reg_wen_i		(id_reg_wen),
		.inst_o			(id_ex_inst_o),
		.inst_addr_o    (id_ex_inst_addr_o),
		.op1_o			(id_ex_op1_o),		
		.op2_o			(id_ex_op2_o),
		.rd_addr_o		(id_ex_rd_addr_o),	
		.reg_wen_o		(id_ex_reg_wen)
		);

	ex ex_inst(
		.inst_i			(id_ex_inst_o),	
		.inst_addr_i	(id_ex_inst_addr_o),
		.op1_i			(id_ex_op1_o),
		.op2_i			(id_ex_op2_o),
		.rd_addr_i		(id_ex_rd_addr_o),
		.rd_wen_i		(id_ex_reg_wen),
		.rd_addr_o		(ex_rd_addr_o),
		.rd_data_o		(ex_rd_data_o),	
		.rd_wen_o       (ex_reg_wen_o)
	);
	


endmodule

regs

module regs(
	input wire clk,
	input wire rst,
	//from id
	input wire[4:0] reg1_raddr_i,
	input wire[4:0] reg2_raddr_i,
	
	//to id
	output reg[31:0] reg1_rdata_o,
	output reg[31:0] reg2_rdata_o,
	
	//from ex
	input wire[4:0] reg_waddr_i,
	input wire[31:0]reg_wdata_i,
	input 			reg_wen

);
	reg[31:0] regs[0:31];
	integer i;

	always @(*)begin
		if(rst == 1'b0)
			reg1_rdata_o <= 32'b0;
		else if(reg1_raddr_i == 5'b0)
			reg1_rdata_o <= 32'b0;
		else if(reg_wen && reg1_raddr_i == reg_waddr_i)
			reg1_rdata_o <= reg_wdata_i;
		else
			reg1_rdata_o <= regs[reg1_raddr_i];
	end
	
	always @(*)begin
		if(rst == 1'b0)
			reg2_rdata_o <= 32'b0;
		else if(reg2_raddr_i == 5'b0)
			reg2_rdata_o <= 32'b0;
		else if(reg_wen && reg2_raddr_i == reg_waddr_i)
			reg2_rdata_o <= reg_wdata_i;
		else
			reg2_rdata_o <= regs[reg2_raddr_i];
	end

	always @(posedge clk)begin
		if(rst == 1'b0) begin
			for(i=0;i<31;i=i+1)begin
				regs[i] <= 32'b0;
			end
		end	
		else if(reg_wen && reg_waddr_i != 5'b0)begin
			regs[reg_waddr_i] <= reg_wdata_i;
		end	
	end

endmodule

rom

module rom(
	input wire[31:0] inst_addr_i,
	output reg[31:0] inst_o
);

	reg[31:0] rom_mem[0:4095];  //4096 个 32b的 空间  //错
	
	always @(*)begin
		inst_o = rom_mem[inst_addr_i>>2];
	end

endmodule

defines

// I type inst
`define INST_TYPE_I 7'b0010011
`define INST_ADDI   3'b000
`define INST_SLTI   3'b010
`define INST_SLTIU  3'b011
`define INST_XORI   3'b100
`define INST_ORI    3'b110
`define INST_ANDI   3'b111
`define INST_SLLI   3'b001
`define INST_SRI    3'b101

// L type inst
`define INST_TYPE_L 7'b0000011
`define INST_LB     3'b000
`define INST_LH     3'b001
`define INST_LW     3'b010
`define INST_LBU    3'b100
`define INST_LHU    3'b101

// S type inst
`define INST_TYPE_S 7'b0100011
`define INST_SB     3'b000
`define INST_SH     3'b001
`define INST_SW     3'b010

// R and M type inst
`define INST_TYPE_R_M 7'b0110011
// R type inst
`define INST_ADD_SUB 3'b000
`define INST_SLL    3'b001
`define INST_SLT    3'b010
`define INST_SLTU   3'b011
`define INST_XOR    3'b100
`define INST_SR     3'b101
`define INST_OR     3'b110
`define INST_AND    3'b111
// M type inst
`define INST_MUL    3'b000
`define INST_MULH   3'b001
`define INST_MULHSU 3'b010
`define INST_MULHU  3'b011
`define INST_DIV    3'b100
`define INST_DIVU   3'b101
`define INST_REM    3'b110
`define INST_REMU   3'b111

// J type inst
`define INST_JAL    7'b1101111
`define INST_JALR   7'b1100111

`define INST_LUI    7'b0110111
`define INST_AUIPC  7'b0010111
`define INST_NOP    32'h00000013
`define INST_NOP_OP 7'b0000001
`define INST_MRET   32'h30200073
`define INST_RET    32'h00008067

`define INST_FENCE  7'b0001111
`define INST_ECALL  32'h73
`define INST_EBREAK 32'h00100073

// J type inst
`define INST_TYPE_B 7'b1100011
`define INST_BEQ    3'b000
`define INST_BNE    3'b001
`define INST_BLT    3'b100
`define INST_BGE    3'b101
`define INST_BLTU   3'b110
`define INST_BGEU   3'b111

dff_set

module dff_set #(
	parameter DW  = 32
)
(
	input wire clk,
	input wire rst,
	input wire [DW-1:0]  set_data, 
	input wire [DW-1:0]  data_i, 
	output reg [DW-1:0]  data_o	
);
	always @(posedge clk)begin
		if(rst == 1'b0)
			data_o <= set_data;
		else
			data_o <= data_i;
	end	

endmodule

ex.v

`include "defines.v"

module ex(
	//from id_ex
	input wire[31:0] inst_i,	
	input wire[31:0] inst_addr_i,
	input wire[31:0] op1_i,
	input wire[31:0] op2_i,
	input wire[4:0]  rd_addr_i,
	input wire 		 rd_wen_i,
	//to regs
	output reg[4:0] rd_addr_o,
	output reg[31:0]rd_data_o,
	output reg 	    rd_wen_o
);

	wire[6:0] opcode; 
	wire[4:0] rd; 
	wire[2:0] func3; 
	wire[4:0] rs1;
	wire[4:0] rs2;
	wire[6:0] func7;
	wire[11:0]imm;
	
	assign opcode = inst_i[6:0];
	assign rd 	  = inst_i[11:7];
	assign func3  = inst_i[14:12];
	assign rs1 	  = inst_i[19:15];
	assign rs2 	  = inst_i[24:20];
	assign func7  = inst_i[31:25];
	assign imm    = inst_i[31:20];
	

	always @(*)begin
		
		case(opcode)
			`INST_TYPE_I:begin
				case(func3)
					`INST_ADDI:begin
						rd_data_o = op1_i + op2_i;
						rd_addr_o = rd_addr_i;
						rd_wen_o  = 1'b1;
					end
					default:begin
						rd_data_o = 32'b0;
						rd_addr_o = 5'b0;
						rd_wen_o  = 1'b0;
					end						
				endcase
			end	
			
			`INST_TYPE_R_M:begin
				case(func3)
					`INST_ADD_SUB:begin
						if(func7 == 7'b000_0000)begin//add
							rd_data_o = op1_i + op2_i;
							rd_addr_o = rd_addr_i;
							rd_wen_o  = 1'b1;
						end
						else begin
							rd_data_o = op2_i - op1_i;
							rd_addr_o = rd_addr_i;
							rd_wen_o  = 1'b1; 								
						end
					end
					default:begin
						rd_data_o = 32'b0;
						rd_addr_o = 5'b0;
						rd_wen_o  = 1'b0;					
					end
				endcase
			end					
			default:begin
				rd_data_o = 32'b0;
				rd_addr_o = 5'b0;
				rd_wen_o  = 1'b0;				
			end
		endcase
	end

	
	
	
endmodule

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值