实验6:CUP的控制模块实现&&CPU全部模块连接

1.CPU控制模块

cpu控制模块进行对保存CPU状态的控制寄存器进行管理,并且对流水线进行控制
cpu控制模块中设有设置和保存CPU状态的控制寄存器
主要处理流水线刷新延迟、程序中断等异常。
这一模块涉及中断处理、流水线刷新延迟,知识点较杂乱,需要配合相关资料进一步研究。

端口定义:

part8.CPU控制模块
    cpu控制模块进行对保存CPU状态的控制寄存器进行管理,并且对流水线进行控制
    cpu控制模块中设有设置和保存CPU状态的控制寄存器
    ctrl:
             /********** Clock & Reset **********/
            input  wire					  clk,			
            input  wire					  reset,		
            /********** Control register interface **********/
            input  wire [`RegAddrBus]	  creg_rd_addr, // Read address
            output reg	[`WordDataBus]	  creg_rd_data, // Read data
            output reg	[`CpuExeModeBus]  exe_mode,		// Execution mode
            /********** Interrupt **********/
            input  wire [`CPU_IRQ_CH-1:0] irq,			// Interrupt request
            output reg					  int_detect,	// Interrupt detection
            /********** ID/EX pipeline register **********/
            input  wire [`WordAddrBus]	  id_pc,		// Program counter
            /********** MEM/WB pipeline register **********/
            input  wire [`WordAddrBus]	  mem_pc,		// Program counter
            input  wire					  mem_en,		// Enable pipeline data
            input  wire					  mem_br_flag,	// Branch flag
            input  wire [`CtrlOpBus]	  mem_ctrl_op,	// Control register operation
            input  wire [`RegAddrBus]	  mem_dst_addr, // Write address
            input  wire [`IsaExpBus]	  mem_exp_code, // Exception code
            input  wire [`WordDataBus]	  mem_out,		// Processing result
            /********** Pipeline control signal **********/
            // Pipeline status
            input  wire					  if_busy,		// IF stage busy
            input  wire					  ld_hazard,	// Load hazard
            input  wire					  mem_busy,		// MEM stage busy
            // Stall signal
            output wire					  if_stall,		// IF stage stall
            output wire					  id_stall,		// ID stage stall
            output wire					  ex_stall,		// EX stage stall
            output wire					  mem_stall,	// MEM stage stall
            // Flush signal
            output wire					  if_flush,		// IF stage flush
            output wire					  id_flush,		// ID stage flush
            output wire					  ex_flush,		// EX stage flush
            output wire					  mem_flush,	// MEM stage flush
            output reg	[`WordAddrBus]	  new_pc		// New program counter
            
            
            
cpu整体连接:
cpu:
     /********** Clock & Reset **********/
	input  wire					  clk,			   // Clock
	input  wire					  clk_,			   // Clock (180)
	input  wire					  reset,		   // Asynchronous reset
	/********** Bus interface **********/
	// IF Stage
	input  wire [`WordDataBus]	  if_bus_rd_data,  // Read data
	input  wire					  if_bus_rdy_,	   // Ready
	input  wire					  if_bus_grnt_,	   // Bus grant
	output wire					  if_bus_req_,	   // Bus request
	output wire [`WordAddrBus]	  if_bus_addr,	   // Address
	output wire					  if_bus_as_,	   // Address strobe
	output wire					  if_bus_rw,	   // Read/Write
	output wire [`WordDataBus]	  if_bus_wr_data,  // Write data
	// MEM Stage
	input  wire [`WordDataBus]	  mem_bus_rd_data, // Read data
	input  wire					  mem_bus_rdy_,	   // Ready
	input  wire					  mem_bus_grnt_,   // Bus grant
	output wire					  mem_bus_req_,	   // Bus reqeuest
	output wire [`WordAddrBus]	  mem_bus_addr,	   // Address
	output wire					  mem_bus_as_,	   // Address strobe
	output wire					  mem_bus_rw,	   // Read/Write
	output wire [`WordDataBus]	  mem_bus_wr_data, // Write data
	/********** Interrupt **********/
	input  wire [`CPU_IRQ_CH-1:0] cpu_irq		   // Interrupt request
    

在这里插入图片描述
代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/04 19:16:52
// Design Name: 
// Module Name: ctrl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"

/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
`include "rom.vh"
`include "spm.vh"


module ctrl(

    /********** Clock & Reset **********/
	input  wire					  clk,			
	input  wire					  reset,		
	/********** Control register interface **********/
	input  wire [`RegAddrBus]	  creg_rd_addr, // Read address
	output reg	[`WordDataBus]	  creg_rd_data, // Read data
	output reg	[`CpuExeModeBus]  exe_mode,		// Execution mode
	/********** Interrupt **********/
	input  wire [`CPU_IRQ_CH-1:0] irq,			// Interrupt request
	output reg					  int_detect,	// Interrupt detection
	/********** ID/EX pipeline register **********/
	input  wire [`WordAddrBus]	  id_pc,		// Program counter
	/********** MEM/WB pipeline register **********/
	input  wire [`WordAddrBus]	  mem_pc,		// Program counter
	input  wire					  mem_en,		// Enable pipeline data
	input  wire					  mem_br_flag,	// Branch flag
	input  wire [`CtrlOpBus]	  mem_ctrl_op,	// Control register operation
	input  wire [`RegAddrBus]	  mem_dst_addr, // Write address
	input  wire [`IsaExpBus]	  mem_exp_code, // Exception code
	input  wire [`WordDataBus]	  mem_out,		// Processing result
	/********** Pipeline control signal **********/
	// Pipeline status
	input  wire					  if_busy,		// IF stage busy
	input  wire					  ld_hazard,	// Load hazard
	input  wire					  mem_busy,		// MEM stage busy
	// Stall signal
	output wire					  if_stall,		// IF stage stall
	output wire					  id_stall,		// ID stage stall
	output wire					  ex_stall,		// EX stage stall
	output wire					  mem_stall,	// MEM stage stall
	// Flush signal
	output wire					  if_flush,		// IF stage flush
	output wire					  id_flush,		// ID stage flush
	output wire					  ex_flush,		// EX stage flush
	output wire					  mem_flush,	// MEM stage flush
	output reg	[`WordAddrBus]	  new_pc		// New program counter
    );
    
    /********** Control register **********/
	reg							 int_en;		// #0 : Interrupt enable
	reg	 [`CpuExeModeBus]		 pre_exe_mode;	// #1 : Execution mode
	reg							 pre_int_en;	// #2 : Interrupt enable
	reg	 [`WordAddrBus]			 epc;			// #3 : Exception program counter
	reg	 [`WordAddrBus]			 exp_vector;	// #4 : Exception vector
	reg	 [`IsaExpBus]			 exp_code;		// #5 : Exception code
	reg							 dly_flag;		// #6 : Delay slot flag
	reg	 [`CPU_IRQ_CH-1:0]		 mask;			// #7 : Interrupt mask

	/********** Internal signal **********/
	reg [`WordAddrBus]		  pre_pc;			// Previous program counter
	reg						  br_flag;			// Branch flag
	
	/********** Pipeline control signal **********/
	// Stall signal
	wire   stall	 = if_busy | mem_busy;
	assign if_stall	 = stall | ld_hazard;
	assign id_stall	 = stall;
	assign ex_stall	 = stall;
	assign mem_stall = stall;
	// Flush signal
	reg	   flush;
	assign if_flush	 = flush;
	assign id_flush	 = flush | ld_hazard;
	assign ex_flush	 = flush;
	assign mem_flush = flush;

	/********** Pipeline flush control **********/
	always @(*) begin
		/* Default value */
		new_pc = `WORD_ADDR_W'h0;
		flush  = `DISABLE;
		/* Pipeline flush */
		if (mem_en == `ENABLE) begin // Enable pipeline data
			if (mem_exp_code != `ISA_EXP_NO_EXP) begin		 // Exception happed
				new_pc = exp_vector;
				flush  = `ENABLE;
			end else if (mem_ctrl_op == `CTRL_OP_EXRT) begin // EXRT instruction
				new_pc = epc;
				flush  = `ENABLE;
			end else if (mem_ctrl_op == `CTRL_OP_WRCR) begin // WRCR instruction
				new_pc = mem_pc;
				flush  = `ENABLE;
			end
		end
	end

	/********** Interrupt detection **********/
	always @(*) begin
		if ((int_en == `ENABLE) && ((|((~mask) & irq)) == `ENABLE)) begin
			int_detect = `ENABLE;
		end else begin
			int_detect = `DISABLE;
		end
	end
   
	/********** Read access **********/
	always @(*) begin
		case (creg_rd_addr)
		   `CREG_ADDR_STATUS	 : begin // #0:Status
			   creg_rd_data = {{`WORD_DATA_W-2{1'b0}}, int_en, exe_mode};
		   end
		   `CREG_ADDR_PRE_STATUS : begin // #1: Status before exception happened
			   creg_rd_data = {{`WORD_DATA_W-2{1'b0}}, 
							   pre_int_en, pre_exe_mode};
		   end
		   `CREG_ADDR_PC		 : begin // #2: Program counter
			   creg_rd_data = {id_pc, `BYTE_OFFSET_W'h0};
		   end
		   `CREG_ADDR_EPC		 : begin // #3: Exception program counter
			   creg_rd_data = {epc, `BYTE_OFFSET_W'h0};
		   end
		   `CREG_ADDR_EXP_VECTOR : begin // #4: Exception vector
			   creg_rd_data = {exp_vector, `BYTE_OFFSET_W'h0};
		   end
		   `CREG_ADDR_CAUSE		 : begin // #5: Exception cause
			   creg_rd_data = {{`WORD_DATA_W-1-`ISA_EXP_W{1'b0}}, 
							   dly_flag, exp_code};
		   end
		   `CREG_ADDR_INT_MASK	 : begin // #6: Interrupt mask
			   creg_rd_data = {{`WORD_DATA_W-`CPU_IRQ_CH{1'b0}}, mask};
		   end
		   `CREG_ADDR_IRQ		 : begin // #6: Interrupt cause
			   creg_rd_data = {{`WORD_DATA_W-`CPU_IRQ_CH{1'b0}}, irq};
		   end
		   `CREG_ADDR_ROM_SIZE	 : begin // #7:ROM's size
			   creg_rd_data = $unsigned(`ROM_SIZE);
		   end
		   `CREG_ADDR_SPM_SIZE	 : begin // #8:SPM's size
			   creg_rd_data = $unsigned(`SPM_SIZE);
		   end
		   `CREG_ADDR_CPU_INFO	 : begin // #9:CPU information
			   creg_rd_data = {`RELEASE_YEAR, `RELEASE_MONTH, 
							   `RELEASE_VERSION, `RELEASE_REVISION};
		   end
		   default				 : begin // Default value
			   creg_rd_data = `WORD_DATA_W'h0;
		   end
		endcase
	end

	/********** CPU control **********/
	always @(posedge clk or `RESET_EDGE reset) begin
		if (reset == `RESET_ENABLE) begin
			/* Asynchronous reset */
			exe_mode	 <= #1 `CPU_KERNEL_MODE;
			int_en		 <= #1 `DISABLE;
			pre_exe_mode <= #1 `CPU_KERNEL_MODE;
			pre_int_en	 <= #1 `DISABLE;
			exp_code	 <= #1 `ISA_EXP_NO_EXP;
			mask		 <= #1 {`CPU_IRQ_CH{`ENABLE}};
			dly_flag	 <= #1 `DISABLE;
			epc			 <= #1 `WORD_ADDR_W'h0;
			exp_vector	 <= #1 `WORD_ADDR_W'h0;
			pre_pc		 <= #1 `WORD_ADDR_W'h0;
			br_flag		 <= #1 `DISABLE;
		end else begin
			/* Update CPU status */
			if ((mem_en == `ENABLE) && (stall == `DISABLE)) begin
				/* Save PC and brach flag */
				//之前的PC保存MEM阶段的PC,分支标志位保存MEM阶段的分支标志位,
				//这些信息在异常发生时使用
				pre_pc		 <= #1 mem_pc;
				br_flag		 <= #1 mem_br_flag;
				/* CPU status control */
				if (mem_exp_code != `ISA_EXP_NO_EXP) begin		 // Exception happened
					exe_mode	 <= #1 `CPU_KERNEL_MODE;
					int_en		 <= #1 `DISABLE;
					pre_exe_mode <= #1 exe_mode;
					pre_int_en	 <= #1 int_en;
					exp_code	 <= #1 mem_exp_code;
					dly_flag	 <= #1 br_flag;
					epc			 <= #1 pre_pc;
				end else if (mem_ctrl_op == `CTRL_OP_EXRT) begin // EXRT instruction
					exe_mode	 <= #1 pre_exe_mode;
					int_en		 <= #1 pre_int_en;
				end else if (mem_ctrl_op == `CTRL_OP_WRCR) begin // WRCR instruction
				   /* Write control register */
					case (mem_dst_addr)
						`CREG_ADDR_STATUS	  : begin // Status
							exe_mode	 <= #1 mem_out[`CregExeModeLoc];
							int_en		 <= #1 mem_out[`CregIntEnableLoc];
						end
						`CREG_ADDR_PRE_STATUS : begin // Status before exception happened
							pre_exe_mode <= #1 mem_out[`CregExeModeLoc];
							pre_int_en	 <= #1 mem_out[`CregIntEnableLoc];
						end
						`CREG_ADDR_EPC		  : begin // Exception program
							epc			 <= #1 mem_out[`WordAddrLoc];
						end
						`CREG_ADDR_EXP_VECTOR : begin // Exception vector
							exp_vector	 <= #1 mem_out[`WordAddrLoc];
						end
						`CREG_ADDR_CAUSE	  : begin // Exception cause
							dly_flag	 <= #1 mem_out[`CregDlyFlagLoc];
							exp_code	 <= #1 mem_out[`CregExpCodeLoc];
						end
						`CREG_ADDR_INT_MASK	  : begin // Interrupt mask
							mask		 <= #1 mem_out[`CPU_IRQ_CH-1:0];
						end
					endcase
				end
			end
		end
	end

	
	
	
endmodule

2.CPU总模块连接

将IF阶段、ID阶段、EX阶段、MEM阶段、cpu控制模块、SPM模块、GPR模块连接起来。
代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/04 19:55:47
// Design Name: 
// Module Name: cpu
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// CPU top module
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"

/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
`include "bus.vh"
`include "spm.vh"

module cpu(
    /********** Clock & Reset **********/
	input  wire					  clk,			   // Clock
	input  wire					  clk_,			   // Clock (180)
	input  wire					  reset,		   // Asynchronous reset
	/********** Bus interface **********/
	// IF Stage
	input  wire [`WordDataBus]	  if_bus_rd_data,  // Read data
	input  wire					  if_bus_rdy_,	   // Ready
	input  wire					  if_bus_grnt_,	   // Bus grant
	output wire					  if_bus_req_,	   // Bus request
	output wire [`WordAddrBus]	  if_bus_addr,	   // Address
	output wire					  if_bus_as_,	   // Address strobe
	output wire					  if_bus_rw,	   // Read/Write
	output wire [`WordDataBus]	  if_bus_wr_data,  // Write data
	// MEM Stage
	input  wire [`WordDataBus]	  mem_bus_rd_data, // Read data
	input  wire					  mem_bus_rdy_,	   // Ready
	input  wire					  mem_bus_grnt_,   // Bus grant
	output wire					  mem_bus_req_,	   // Bus reqeuest
	output wire [`WordAddrBus]	  mem_bus_addr,	   // Address
	output wire					  mem_bus_as_,	   // Address strobe
	output wire					  mem_bus_rw,	   // Read/Write
	output wire [`WordDataBus]	  mem_bus_wr_data, // Write data
	/********** Interrupt **********/
	input  wire [`CPU_IRQ_CH-1:0] cpu_irq		   // Interrupt request
    
    );
    
    /********** Pipeline register **********/
	// IF/ID
	wire [`WordAddrBus]			 if_pc;			 
	wire [`WordDataBus]			 if_insn;		 
	wire						 if_en;			
	// ID/EX pipeline register
	wire [`WordAddrBus]			 id_pc;			 
	wire						 id_en;			
	wire [`AluOpBus]			 id_alu_op;		
	wire [`WordDataBus]			 id_alu_in_0;	
	wire [`WordDataBus]			 id_alu_in_1;	 
	wire						 id_br_flag;	
	wire [`MemOpBus]			 id_mem_op;		
	wire [`WordDataBus]			 id_mem_wr_data;
	wire [`CtrlOpBus]			 id_ctrl_op;	
	wire [`RegAddrBus]			 id_dst_addr;	
	wire						 id_gpr_we_;
	wire [`IsaExpBus]			 id_exp_code;
	// EX/MEM pipeline register
	wire [`WordAddrBus]			 ex_pc;	
	wire						 ex_en;			 
	wire						 ex_br_flag;	 
	wire [`MemOpBus]			 ex_mem_op;		 
	wire [`WordDataBus]			 ex_mem_wr_data; 
	wire [`CtrlOpBus]			 ex_ctrl_op;	 
	wire [`RegAddrBus]			 ex_dst_addr;	 
	wire						 ex_gpr_we_;	
	wire [`IsaExpBus]			 ex_exp_code;	
	wire [`WordDataBus]			 ex_out;		
	// MEM/WB pipeline register
	wire [`WordAddrBus]			 mem_pc;		
	wire						 mem_en;		
	wire						 mem_br_flag;	 
	wire [`CtrlOpBus]			 mem_ctrl_op;	
	wire [`RegAddrBus]			 mem_dst_addr;	 
	wire						 mem_gpr_we_;	 
	wire [`IsaExpBus]			 mem_exp_code;	 
	wire [`WordDataBus]			 mem_out;		 
	/********** Pipeline control signal **********/
	// Stall signal
	wire						 if_stall;		 // IF stage
	wire						 id_stall;		 // ID stage
	wire						 ex_stall;		 // EX stage
	wire						 mem_stall;		 // MEM stage
	// Flush signal
	wire						 if_flush;		 // IF stage
	wire						 id_flush;		 // ID stage
	wire						 ex_flush;		 // EX stage
	wire						 mem_flush;		 // MEM stage
	// Busy signal
	wire						 if_busy;		 // IF stage
	wire						 mem_busy;		 // MEM stage
	// Other control signal
	wire [`WordAddrBus]			 new_pc;		 // New program counter
	wire [`WordAddrBus]			 br_addr;		 // Branch address
	wire						 br_taken;		 // Branch taken
	wire						 ld_hazard;		 // Load hazard
	/********** GPR signal **********/
	wire [`WordDataBus]			 gpr_rd_data_0;	
	wire [`WordDataBus]			 gpr_rd_data_1;	
	wire [`RegAddrBus]			 gpr_rd_addr_0;	
	wire [`RegAddrBus]			 gpr_rd_addr_1;	
	/********** Control register signal **********/
	wire [`CpuExeModeBus]		 exe_mode;		
	wire [`WordDataBus]			 creg_rd_data;	 
	wire [`RegAddrBus]			 creg_rd_addr;	 
	/********** Interrupt Request **********/
	wire						 int_detect;	
	/********** Scratchpad memory signal **********/
	// IF stage
	wire [`WordDataBus]			 if_spm_rd_data; 
	wire [`WordAddrBus]			 if_spm_addr;	 
	wire						 if_spm_as_;	
	wire						 if_spm_rw;		
	wire [`WordDataBus]			 if_spm_wr_data;
	// MEM stage
	wire [`WordDataBus]			 mem_spm_rd_data; 
	wire [`WordAddrBus]			 mem_spm_addr;	  
	wire						 mem_spm_as_;	 
	wire						 mem_spm_rw;
	wire [`WordDataBus]			 mem_spm_wr_data; 
	/********** Forwarding signal **********/
	wire [`WordDataBus]			 ex_fwd_data;	  // EX stage
	wire [`WordDataBus]			 mem_fwd_data;	  // MEM stage

	/********** IF stage **********/
	if_stage if_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** SPM interface **********/
		.spm_rd_data	(if_spm_rd_data),	
		.spm_addr		(if_spm_addr),		
		.spm_as_		(if_spm_as_),		
		.spm_rw			(if_spm_rw),		
		.spm_wr_data	(if_spm_wr_data),	
		/********** Bus interface **********/
		.bus_rd_data	(if_bus_rd_data),	
		.bus_rdy_		(if_bus_rdy_),	
		.bus_grnt_		(if_bus_grnt_),	
		.bus_req_		(if_bus_req_),		
		.bus_addr		(if_bus_addr),		
		.bus_as_		(if_bus_as_),		
		.bus_rw			(if_bus_rw),		
		.bus_wr_data	(if_bus_wr_data),	
		/********** Pipeline control signal **********/
		.stall			(if_stall),			
		.flush			(if_flush),			
		.new_pc			(new_pc),			
		.br_taken		(br_taken),			
		.br_addr		(br_addr),			
		.busy			(if_busy),		
		/********** IF/ID pipeline register **********/
		.if_pc			(if_pc),			
		.if_insn		(if_insn),			
		.if_en			(if_en)				
	);

	/********** ID stage **********/
	id_stage id_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** GPR interface **********/
		.gpr_rd_data_0	(gpr_rd_data_0),	
		.gpr_rd_data_1	(gpr_rd_data_1),	
		.gpr_rd_addr_0	(gpr_rd_addr_0),	
		.gpr_rd_addr_1	(gpr_rd_addr_1),	
		/********** Forwarding **********/
		// Forwarding from EX stage
		.ex_en			(ex_en),			
		.ex_fwd_data	(ex_fwd_data),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		// Forwarding from MEM stage
		.mem_fwd_data	(mem_fwd_data),		
		/********** Control register interface **********/
		.exe_mode		(exe_mode),		
		.creg_rd_data	(creg_rd_data),	
		.creg_rd_addr	(creg_rd_addr),		
		/********** Pipeline control signal **********/
	   .stall		   (id_stall),	
		.flush			(id_flush),			
		.br_addr		(br_addr),			
		.br_taken		(br_taken),			
		.ld_hazard		(ld_hazard),		
		/********** IF/ID pipeline register **********/
		.if_pc			(if_pc),			
		.if_insn		(if_insn),			
		.if_en			(if_en),			
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		.id_en			(id_en),			
		.id_alu_op		(id_alu_op),		
		.id_alu_in_0	(id_alu_in_0),		
		.id_alu_in_1	(id_alu_in_1),		
		.id_br_flag		(id_br_flag),	
		.id_mem_op		(id_mem_op),		
		.id_mem_wr_data (id_mem_wr_data),	
		.id_ctrl_op		(id_ctrl_op),	
		.id_dst_addr	(id_dst_addr),		
		.id_gpr_we_		(id_gpr_we_),		
		.id_exp_code	(id_exp_code)		
	);

	/********** EX stage **********/
	ex_stage ex_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Pipeline control signal **********/
		.stall			(ex_stall),			
		.flush			(ex_flush),			
		.int_detect		(int_detect),		
		/********** Forwarding **********/
		.fwd_data		(ex_fwd_data),		
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		.id_en			(id_en),			
		.id_alu_op		(id_alu_op),		
		.id_alu_in_0	(id_alu_in_0),		
		.id_alu_in_1	(id_alu_in_1),		
		.id_br_flag		(id_br_flag),		
		.id_mem_op		(id_mem_op),		
		.id_mem_wr_data (id_mem_wr_data),	
		.id_ctrl_op		(id_ctrl_op),		
		.id_dst_addr	(id_dst_addr),		
		.id_gpr_we_		(id_gpr_we_),		
		.id_exp_code	(id_exp_code),		
		/********** EX/MEM pipeline register **********/
		.ex_pc			(ex_pc),			
		.ex_en			(ex_en),			
		.ex_br_flag		(ex_br_flag),		
		.ex_mem_op		(ex_mem_op),		
		.ex_mem_wr_data (ex_mem_wr_data),	
		.ex_ctrl_op		(ex_ctrl_op),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		.ex_exp_code	(ex_exp_code),		
		.ex_out			(ex_out)			
	);

	/********** MEM Stage **********/
	mem_stage mem_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Pipeline control signal **********/
		.stall			(mem_stall),		
		.flush			(mem_flush),		
		.busy			(mem_busy),			
		/********** Forwarding **********/
		.fwd_data		(mem_fwd_data),		
		/********** SPM interface **********/
		.spm_rd_data	(mem_spm_rd_data),	
		.spm_addr		(mem_spm_addr),		
		.spm_as_		(mem_spm_as_),		
		.spm_rw			(mem_spm_rw),		
		.spm_wr_data	(mem_spm_wr_data),	
		/********** Bus interface **********/
		.bus_rd_data	(mem_bus_rd_data),	
		.bus_rdy_		(mem_bus_rdy_),		
		.bus_grnt_		(mem_bus_grnt_),	
		.bus_req_		(mem_bus_req_),		
		.bus_addr		(mem_bus_addr),		
		.bus_as_		(mem_bus_as_),		
		.bus_rw			(mem_bus_rw),		
		.bus_wr_data	(mem_bus_wr_data),	
		/********** EX/MEM pipeline register **********/
		.ex_pc			(ex_pc),			
		.ex_en			(ex_en),			
		.ex_br_flag		(ex_br_flag),		
		.ex_mem_op		(ex_mem_op),		
		.ex_mem_wr_data (ex_mem_wr_data),	
		.ex_ctrl_op		(ex_ctrl_op),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		.ex_exp_code	(ex_exp_code),		
		.ex_out			(ex_out),			
		/********** MEM/WB pipeline register **********/
		.mem_pc			(mem_pc),			
		.mem_en			(mem_en),			
		.mem_br_flag	(mem_br_flag),		
		.mem_ctrl_op	(mem_ctrl_op),		
		.mem_dst_addr	(mem_dst_addr),		
		.mem_gpr_we_	(mem_gpr_we_),		
		.mem_exp_code	(mem_exp_code),		
		.mem_out		(mem_out)			
	);

	/********** Control unit **********/
	ctrl ctrl (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Control register interface **********/
		.creg_rd_addr	(creg_rd_addr),		
		.creg_rd_data	(creg_rd_data),		
		.exe_mode		(exe_mode),			
		/********** Interrupt **********/
		.irq			(cpu_irq),			
		.int_detect		(int_detect),		
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		/********** MEM/WB pipeline register **********/
		.mem_pc			(mem_pc),			
		.mem_en			(mem_en),			
		.mem_br_flag	(mem_br_flag),		
		.mem_ctrl_op	(mem_ctrl_op),		
		.mem_dst_addr	(mem_dst_addr),		
		.mem_exp_code	(mem_exp_code),		
		.mem_out		(mem_out),			
		/********** Pipeline control signal **********/
		// Status of pipeline
		.if_busy		(if_busy),			
		.ld_hazard		(ld_hazard),		
		.mem_busy		(mem_busy),			
		// stall singal
		.if_stall		(if_stall),			
		.id_stall		(id_stall),			
		.ex_stall		(ex_stall),			
		.mem_stall		(mem_stall),		
		// Flush signal
		.if_flush		(if_flush),			
		.id_flush		(id_flush),			
		.ex_flush		(ex_flush),		
		.mem_flush		(mem_flush),		
		// New program counter
		.new_pc			(new_pc)			
	);

	/********** GPR **********/
	gpr gpr (
		/********** Clock & Reset **********/
		.clk	   (clk),					
		.reset	   (reset),					
		/********** Read port 0 **********/
		.rd_addr_0 (gpr_rd_addr_0),			
		.rd_data_0 (gpr_rd_data_0),			
		/********** Read port 1 **********/
		.rd_addr_1 (gpr_rd_addr_1),			
		.rd_data_1 (gpr_rd_data_1),			
		/********** Write port **********/
		.we_	   (mem_gpr_we_),			
		.wr_addr   (mem_dst_addr),			
		.wr_data   (mem_out)				
	);

	/********** Scratchpad memory **********/
	spm spm (
		/********** Clock **********/
		.clk			 (clk_),					 
		/********** PortA : IF stage **********/
		.if_spm_addr	 (if_spm_addr[`SpmAddrLoc]), 
		.if_spm_as_		 (if_spm_as_),				  
		.if_spm_rw		 (if_spm_rw),				
		.if_spm_wr_data	 (if_spm_wr_data),			 
		.if_spm_rd_data	 (if_spm_rd_data),			  
		/********** PortB : MEM stage **********/
		.mem_spm_addr	 (mem_spm_addr[`SpmAddrLoc]), 
		.mem_spm_as_	 (mem_spm_as_),				
		.mem_spm_rw		 (mem_spm_rw),				 
		.mem_spm_wr_data (mem_spm_wr_data),			  
		.mem_spm_rd_data (mem_spm_rd_data)			 
	);
    
endmodule

3.仿真验证

这边对于cpu控制寄存器对应模块的相关内容还未掌握,暂时未涉及到中断等异常的判断处理。
验证思路:
由于top模块连接中if_bus_rd_data作为输入源,
在testbench中将if_bus_rd_data可设为reg类型
而if_pc在定义时是wire类型,不好进行对应赋值。
这边将指令传输给if_bus_rd_data,进行寄存器之间的加法运算。
先将需要进行计算的数据放入寄存器群中,这边将实现100+200=300的计算,并将计算结果写入gpr[3].

  gpr[2]<=32'd100;
  gpr[1]<=32'd200;

仿真代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/04 21:25:14
// Design Name: 
// Module Name: cpu_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"

/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
`include "bus.vh"
`include "spm.vh"

module cpu_test(

    );
         
    //端口定义
     /********** Clock & Reset **********/
	  reg					  clk;			   // Clock
	  reg					  clk_;			   // Clock (180)
	  reg					  reset;		   // Asynchronous reset
	/********** Bus interface **********/
	// IF Stage
	  reg [`WordDataBus]	  if_bus_rd_data;  // Read data
	  reg					  if_bus_rdy_;	   // Ready
	  reg					  if_bus_grnt_;	   // Bus grant
	 wire					  if_bus_req_;	   // Bus request
	 wire [`WordAddrBus]	  if_bus_addr;	   // Address
	 wire					  if_bus_as_;	   // Address strobe
	 wire					  if_bus_rw;	   // Read/Write
	 wire [`WordDataBus]	  if_bus_wr_data;  // Write data
	// MEM Stage
	  reg [`WordDataBus]	  mem_bus_rd_data; // Read data
	  reg					  mem_bus_rdy_;	   // Ready
	  reg					  mem_bus_grnt_;   // Bus grant
	 wire					  mem_bus_req_;	   // Bus reqeuest
	 wire [`WordAddrBus]	  mem_bus_addr;	   // Address
	 wire					  mem_bus_as_;	   // Address strobe
	 wire					  mem_bus_rw;	   // Read/Write
	 wire [`WordDataBus]	  mem_bus_wr_data; // Write data
	/********** Interrupt **********/
	  reg [`CPU_IRQ_CH-1:0] cpu_irq;	   // Interrupt request
	  
	   /********** Pipeline register **********/
	// IF/ID
	wire [`WordAddrBus]			 if_pc;			 
	wire [`WordDataBus]			 if_insn;		 
	wire						 if_en;			
	// ID/EX pipeline register
	wire [`WordAddrBus]			 id_pc;			 
	wire						 id_en;			
	wire [`AluOpBus]			 id_alu_op;		
	wire [`WordDataBus]			 id_alu_in_0;	
	wire [`WordDataBus]			 id_alu_in_1;	 
	wire						 id_br_flag;	
	wire [`MemOpBus]			 id_mem_op;		
	wire [`WordDataBus]			 id_mem_wr_data;
	wire [`CtrlOpBus]			 id_ctrl_op;	
	wire [`RegAddrBus]			 id_dst_addr;	
	wire						 id_gpr_we_;
	wire [`IsaExpBus]			 id_exp_code;
	// EX/MEM pipeline register
	wire [`WordAddrBus]			 ex_pc;	
	wire						 ex_en;			 
	wire						 ex_br_flag;	 
	wire [`MemOpBus]			 ex_mem_op;		 
	wire [`WordDataBus]			 ex_mem_wr_data; 
	wire [`CtrlOpBus]			 ex_ctrl_op;	 
	wire [`RegAddrBus]			 ex_dst_addr;	 
	wire						 ex_gpr_we_;	
	wire [`IsaExpBus]			 ex_exp_code;	
	wire [`WordDataBus]			 ex_out;		
	// MEM/WB pipeline register
	wire [`WordAddrBus]			 mem_pc;		
	wire						 mem_en;		
	wire						 mem_br_flag;	 
	wire [`CtrlOpBus]			 mem_ctrl_op;	
	wire [`RegAddrBus]			 mem_dst_addr;	 
	wire						 mem_gpr_we_;	 
	wire [`IsaExpBus]			 mem_exp_code;	 
	wire [`WordDataBus]			 mem_out;		 
	/********** Pipeline control signal **********/
	// Stall signal
	wire						 if_stall;		 // IF stage
	wire						 id_stall;		 // ID stage
	wire				          ex_stall;		 // EX stage
	wire						 mem_stall;		 // MEM stage
	// Flush signal
	wire    					if_flush;		 // IF stage
	wire						 id_flush;		 // ID stage
	wire						 ex_flush;		 // EX stage
	wire						 mem_flush;		 // MEM stage
	// Busy signal
	wire						 if_busy;		 // IF stage
	wire						 mem_busy;		 // MEM stage
	// Other control signal
	wire [`WordAddrBus]			 new_pc;		 // New program counter
	wire [`WordAddrBus]			 br_addr;		 // Branch address
	wire						 br_taken;		 // Branch taken
	wire						 ld_hazard;		 // Load hazard
	/********** GPR signal **********/
	wire [`WordDataBus]			 gpr_rd_data_0;	
	wire [`WordDataBus]			 gpr_rd_data_1;	
	wire [`RegAddrBus]			 gpr_rd_addr_0;	
	wire [`RegAddrBus]			 gpr_rd_addr_1;	
	/********** Control register signal **********/
	wire [`CpuExeModeBus]		 exe_mode;		
	wire [`WordDataBus]			 creg_rd_data;	 
	wire [`RegAddrBus]			 creg_rd_addr;	 
	/********** Interrupt Request **********/
	wire						 int_detect;	
	/********** Scratchpad memory signal **********/
	// IF stage
	wire [`WordDataBus]			 if_spm_rd_data; 
	wire [`WordAddrBus]			 if_spm_addr;	 
	wire						 if_spm_as_;	
	wire						 if_spm_rw;		
	wire [`WordDataBus]			 if_spm_wr_data;
	// MEM stage
	wire [`WordDataBus]			 mem_spm_rd_data; 
	wire [`WordAddrBus]			 mem_spm_addr;	  
	wire						 mem_spm_as_;	 
	wire						 mem_spm_rw;
	wire [`WordDataBus]			 mem_spm_wr_data; 
	/********** Forwarding signal **********/
	wire [`WordDataBus]			 ex_fwd_data;	  // EX stage
	wire [`WordDataBus]			 mem_fwd_data;	  // MEM stage
    
    //时钟激励:
             integer i;
             parameter STEP=100;
    
             always#(STEP/2)begin
             clk<=~clk;
             clk_ <=~clk_;
            
             end
    //实例化
    /********** IF stage **********/
	if_stage if_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** SPM interface **********/
		.spm_rd_data	(if_spm_rd_data),	
		.spm_addr		(if_spm_addr),		
		.spm_as_		(if_spm_as_),		
		.spm_rw			(if_spm_rw),		
		.spm_wr_data	(if_spm_wr_data),	
		/********** Bus interface **********/
		.bus_rd_data	(if_bus_rd_data),	
		.bus_rdy_		(if_bus_rdy_),	
		.bus_grnt_		(if_bus_grnt_),	
		.bus_req_		(if_bus_req_),		
		.bus_addr		(if_bus_addr),		
		.bus_as_		(if_bus_as_),		
		.bus_rw			(if_bus_rw),		
		.bus_wr_data	(if_bus_wr_data),	
		/********** Pipeline control signal **********/
		.stall			(if_stall),			
		.flush			(if_flush),			
		.new_pc			(new_pc),			
		.br_taken		(br_taken),			
		.br_addr		(br_addr),			
		.busy			(if_busy),		
		/********** IF/ID pipeline register **********/
		.if_pc			(if_pc),			
		.if_insn		(if_insn),			
		.if_en			(if_en)				
	);

	/********** ID stage **********/
	id_stage id_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** GPR interface **********/
		.gpr_rd_data_0	(gpr_rd_data_0),	
		.gpr_rd_data_1	(gpr_rd_data_1),	
		.gpr_rd_addr_0	(gpr_rd_addr_0),	
		.gpr_rd_addr_1	(gpr_rd_addr_1),	
		/********** Forwarding **********/
		// Forwarding from EX stage
		.ex_en			(ex_en),			
		.ex_fwd_data	(ex_fwd_data),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		// Forwarding from MEM stage
		.mem_fwd_data	(mem_fwd_data),		
		/********** Control register interface **********/
		.exe_mode		(exe_mode),		
		.creg_rd_data	(creg_rd_data),	
		.creg_rd_addr	(creg_rd_addr),		
		/********** Pipeline control signal **********/
	   .stall		   (id_stall),	
		.flush			(id_flush),			
		.br_addr		(br_addr),			
		.br_taken		(br_taken),			
		.ld_hazard		(ld_hazard),		
		/********** IF/ID pipeline register **********/
		.if_pc			(if_pc),			
		.if_insn		(if_insn),			
		.if_en			(if_en),			
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		.id_en			(id_en),			
		.id_alu_op		(id_alu_op),		
		.id_alu_in_0	(id_alu_in_0),		
		.id_alu_in_1	(id_alu_in_1),		
		.id_br_flag		(id_br_flag),	
		.id_mem_op		(id_mem_op),		
		.id_mem_wr_data (id_mem_wr_data),	
		.id_ctrl_op		(id_ctrl_op),	
		.id_dst_addr	(id_dst_addr),		
		.id_gpr_we_		(id_gpr_we_),		
		.id_exp_code	(id_exp_code)		
	);

	/********** EX stage **********/
	ex_stage ex_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Pipeline control signal **********/
		.stall			(ex_stall),			
		.flush			(ex_flush),			
		.int_detect		(int_detect),		
		/********** Forwarding **********/
		.fwd_data		(ex_fwd_data),		
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		.id_en			(id_en),			
		.id_alu_op		(id_alu_op),		
		.id_alu_in_0	(id_alu_in_0),		
		.id_alu_in_1	(id_alu_in_1),		
		.id_br_flag		(id_br_flag),		
		.id_mem_op		(id_mem_op),		
		.id_mem_wr_data (id_mem_wr_data),	
		.id_ctrl_op		(id_ctrl_op),		
		.id_dst_addr	(id_dst_addr),		
		.id_gpr_we_		(id_gpr_we_),		
		.id_exp_code	(id_exp_code),		
		/********** EX/MEM pipeline register **********/
		.ex_pc			(ex_pc),			
		.ex_en			(ex_en),			
		.ex_br_flag		(ex_br_flag),		
		.ex_mem_op		(ex_mem_op),		
		.ex_mem_wr_data (ex_mem_wr_data),	
		.ex_ctrl_op		(ex_ctrl_op),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		.ex_exp_code	(ex_exp_code),		
		.ex_out			(ex_out)			
	);

	/********** MEM Stage **********/
	mem_stage mem_stage (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Pipeline control signal **********/
		.stall			(mem_stall),		
		.flush			(mem_flush),		
		.busy			(mem_busy),			
		/********** Forwarding **********/
		.fwd_data		(mem_fwd_data),		
		/********** SPM interface **********/
		.spm_rd_data	(mem_spm_rd_data),	
		.spm_addr		(mem_spm_addr),		
		.spm_as_		(mem_spm_as_),		
		.spm_rw			(mem_spm_rw),		
		.spm_wr_data	(mem_spm_wr_data),	
		/********** Bus interface **********/
		.bus_rd_data	(mem_bus_rd_data),	
		.bus_rdy_		(mem_bus_rdy_),		
		.bus_grnt_		(mem_bus_grnt_),	
		.bus_req_		(mem_bus_req_),		
		.bus_addr		(mem_bus_addr),		
		.bus_as_		(mem_bus_as_),		
		.bus_rw			(mem_bus_rw),		
		.bus_wr_data	(mem_bus_wr_data),	
		/********** EX/MEM pipeline register **********/
		.ex_pc			(ex_pc),			
		.ex_en			(ex_en),			
		.ex_br_flag		(ex_br_flag),		
		.ex_mem_op		(ex_mem_op),		
		.ex_mem_wr_data (ex_mem_wr_data),	
		.ex_ctrl_op		(ex_ctrl_op),		
		.ex_dst_addr	(ex_dst_addr),		
		.ex_gpr_we_		(ex_gpr_we_),		
		.ex_exp_code	(ex_exp_code),		
		.ex_out			(ex_out),			
		/********** MEM/WB pipeline register **********/
		.mem_pc			(mem_pc),			
		.mem_en			(mem_en),			
		.mem_br_flag	(mem_br_flag),		
		.mem_ctrl_op	(mem_ctrl_op),		
		.mem_dst_addr	(mem_dst_addr),		
		.mem_gpr_we_	(mem_gpr_we_),		
		.mem_exp_code	(mem_exp_code),		
		.mem_out		(mem_out)			
	);

	/********** Control unit **********/
	ctrl ctrl (
		/********** Clock & Reset **********/
		.clk			(clk),				
		.reset			(reset),			
		/********** Control register interface **********/
		.creg_rd_addr	(creg_rd_addr),		
		.creg_rd_data	(creg_rd_data),		
		.exe_mode		(exe_mode),			
		/********** Interrupt **********/
		.irq			(cpu_irq),			
		.int_detect		(int_detect),		
		/********** ID/EX pipeline register **********/
		.id_pc			(id_pc),			
		/********** MEM/WB pipeline register **********/
		.mem_pc			(mem_pc),			
		.mem_en			(mem_en),			
		.mem_br_flag	(mem_br_flag),		
		.mem_ctrl_op	(mem_ctrl_op),		
		.mem_dst_addr	(mem_dst_addr),		
		.mem_exp_code	(mem_exp_code),		
		.mem_out		(mem_out),			
		/********** Pipeline control signal **********/
		// Status of pipeline
		.if_busy		(if_busy),			
		.ld_hazard		(ld_hazard),		
		.mem_busy		(mem_busy),			
		// stall singal
		.if_stall		(if_stall),			
		.id_stall		(id_stall),			
		.ex_stall		(ex_stall),			
		.mem_stall		(mem_stall),		
		// Flush signal
		.if_flush		(if_flush),			
		.id_flush		(id_flush),			
		.ex_flush		(ex_flush),		
		.mem_flush		(mem_flush),		
		// New program counter
		.new_pc			(new_pc)			
	);

	/********** GPR **********/
	gpr gpr (
		/********** Clock & Reset **********/
		.clk	   (clk),					
		.reset	   (reset),					
		/********** Read port 0 **********/
		.rd_addr_0 (gpr_rd_addr_0),			
		.rd_data_0 (gpr_rd_data_0),			
		/********** Read port 1 **********/
		.rd_addr_1 (gpr_rd_addr_1),			
		.rd_data_1 (gpr_rd_data_1),			
		/********** Write port **********/
		.we_	   (mem_gpr_we_),			
		.wr_addr   (mem_dst_addr),			
		.wr_data   (mem_out)				
	);

	/********** Scratchpad memory **********/
	spm spm (
		/********** Clock **********/
		.clk			 (clk_),					 
		/********** PortA : IF stage **********/
		.if_spm_addr	 (if_spm_addr[`SpmAddrLoc]), 
		.if_spm_as_		 (if_spm_as_),				  
		.if_spm_rw		 (if_spm_rw),				
		.if_spm_wr_data	 (if_spm_wr_data),			 
		.if_spm_rd_data	 (if_spm_rd_data),			  
		/********** PortB : MEM stage **********/
		.mem_spm_addr	 (mem_spm_addr[`SpmAddrLoc]), 
		.mem_spm_as_	 (mem_spm_as_),				
		.mem_spm_rw		 (mem_spm_rw),				 
		.mem_spm_wr_data (mem_spm_wr_data),			  
		.mem_spm_rd_data (mem_spm_rd_data)			 
	);
   //测试模式:
  
  
      
          

    initial
     begin
     
    clk<=1;
    clk_<=0;
    reset<=`RESET_ENABLE;
    #(STEP*3/4)
    #STEP begin
    reset<=`RESET_DISABLE;
    #STEP
    if_bus_rd_data<= {{`ISA_OP_ADDSR},{5'b00001},{5'b00010},{5'b00011},{11{1'b0}}};
    #STEP
    if_bus_grnt_<=`ENABLE_;
    #STEP
    if_bus_rdy_ <=`ENABLE_;
    
  
           end
           
  end   
              
endmodule

仿真结果:
1.IF模块取出代码,这边我们将指令赋值给if_bus_rd_data。
if寄存器将会存储下指令(insn)传递给ID模块。在这里插入图片描述
2.在ID模块的解码中,将指令分解。得到对于操作和操作数地址
接着传给ID寄存器,ID寄存器传递指令给EX模块
下图显示操作数为gpr【1】和gpr【2】,数值分别为100和200

在这里插入图片描述
这边将需要的信号存入id寄存器中,op=4,alu0=100,alu1=200,计算返回寄存器为gpr[3].
在这里插入图片描述
3.EX阶段进行指令的执行,得到out=300的结果,保存到ex寄存器,并传递给mem模块。
alu结果:
在这里插入图片描述
ex寄存器:
在这里插入图片描述
4.MEM阶段,将ex结果写回寄存器群中,dst_addr=3,即写回gpr[3]。注意gpr_we写入标志位这时是有效的。仿真结束。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值