实验2:CUP的取指IF阶段实现

1.通用寄存器,三个通用寄存器,两个读取,一个写入
gpr
    input wire clk,
    input wire reset,
    /********** 读端口0 **********/
	input  wire [`RegAddrBus]  rd_addr_0,		   // Read address 位宽5
	output wire [`WordDataBus] rd_data_0,		   // Read data  位宽32
	/********** 读端口1 **********/
	input  wire [`RegAddrBus]  rd_addr_1,		   // Read address 位宽5
	output wire [`WordDataBus] rd_data_1,		   // Read data 位宽32
	/********** 写端口 **********/
	input  wire				   we_,				   // Write enable 位宽1
	input  wire [`RegAddrBus]  wr_addr,			   // Write address 位宽5
	input  wire [`WordDataBus] wr_data			   // Write data  位宽32
	
2.SPM专用内存
spm
    input wire clk,
    //portA:IF阶段
    input  wire [`SpmAddrBus]  if_spm_addr,		// Address 位宽12
	input  wire				   if_spm_as_,		// Address strobe
	input  wire				   if_spm_rw,		// Read/Write
	input  wire [`WordDataBus] if_spm_wr_data,	// Write data 位宽32
	output wire [`WordDataBus] if_spm_rd_data,	// Read data 位宽32
     //portB:MEM阶段
    input  wire [`SpmAddrBus]  mem_spm_addr,		// Address 位宽12
	input  wire				   mem_spm_as_,		// Address strobe
	input  wire				   mem_spm_rw,		// Read/Write
	input  wire [`WordDataBus] mem_spm_wr_data,	// Write data 位宽32
	output wire [`WordDataBus] mem_spm_rd_data	// Read data 位宽32

1.通用寄存器Gpr:

指令最大可以指定三个寄存器为操作数,
其中两个寄存器读取值,然后向另一个寄存器写入值。因此寄存器堆为两个读取端口,一个写入端口
代码如下:

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

/********** Local header **********/
`include "cpu.vh"


module gpr(
     //时钟和复位
    input wire clk,
    input wire reset,
    /********** 读端口0 **********/
	input  wire [`RegAddrBus]  rd_addr_0,		   // Read address 位宽5
	output wire [`WordDataBus] rd_data_0,		   // Read data  位宽32
	/********** 读端口1 **********/
	input  wire [`RegAddrBus]  rd_addr_1,		   // Read address 位宽5
	output wire [`WordDataBus] rd_data_1,		   // Read data 位宽32
	/********** 写端口 **********/
	input  wire				   we_,				   // Write enable 位宽1
	input  wire [`RegAddrBus]  wr_addr,			   // Write address 位宽5
	input  wire [`WordDataBus] wr_data			   // Write data  位宽32

    );
    /********** Internal signal **********/
	reg [`WordDataBus]		   gpr [`REG_NUM-1:0]; // Register array 32*32
	integer					   i;              //初始化用迭代器,位宽32
	
	//读取端口0
	assign rd_data_0 =((we_==`ENABLE)&&(wr_addr==rd_addr_0))?
	                   wr_data:gpr[rd_addr_0];
     //读取端口1
     assign rd_data_1 =((we_==`ENABLE)&&(wr_addr==rd_addr_1))?
	                   wr_data:gpr[rd_addr_1]; 
	                   
   //异步复位
    always @(posedge clk or `RESET_EDGE reset)
    begin
    if(reset==`RESET_ENABLE)
        begin
        for (i=0;i<`REG_NUM;i=i+1)
        //`define REG_NUM				 32
            begin
            //`define WORD_DATA_W			32
                gpr[i] <= #1 `WORD_DATA_W'h0;
            end
            
        end
        else
            begin
                if(we_==`ENABLE_)
                    begin
                    gpr[wr_addr]<= #1 wr_data;
                    end
            end 
    end
 endmodule

2.专用内存SPM

CPU可以不经过总线直接访问的专用内存。在(IF阶段和MEM阶段使用)存储器使用FPGA的Dual Port RAM 实现。
代码如下:

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

/********** Local header **********/
`include "spm.vh"

module spm(
    //时钟
    input wire clk,
    //portA:IF阶段
    input  wire [`SpmAddrBus]  if_spm_addr,		// Address 位宽12
	input  wire				   if_spm_as_,		// Address strobe
	input  wire				   if_spm_rw,		// Read/Write
	input  wire [`WordDataBus] if_spm_wr_data,	// Write data 位宽32
	output wire [`WordDataBus] if_spm_rd_data,	// Read data 位宽32
     //portB:MEM阶段
    input  wire [`SpmAddrBus]  mem_spm_addr,		// Address 位宽12
	input  wire				   mem_spm_as_,		// Address strobe
	input  wire				   mem_spm_rw,		// Read/Write
	input  wire [`WordDataBus] mem_spm_wr_data,	// Write data 位宽32
	output wire [`WordDataBus] mem_spm_rd_data	// Read data 位宽32

    );
    /********** Write enable signal写入有效信号 **********/
	reg						   wea;			// Port A
	reg						   web;			// Port B
	//写入有效信号的生成
	always @(*)
	begin
	//A端口
	//	`define WRITE				1'b0
	//	`define MEM_ENABLE	  1'b1	
	//`define MEM_DISABLE	  1'b0	
	if((if_spm_as_==`ENABLE_)&&(if_spm_rw==`WRITE))
	   begin
	   wea =`MEM_ENABLE;
	   end
	else 
	   begin
	   wea=`MEM_DISABLE;
	   end
	
    //B端口   
    if((mem_spm_as_==`ENABLE_)&&(mem_spm_rw==`WRITE))
	   begin
	   web =`MEM_ENABLE;
	   end
	else 
	   begin
	   web=`MEM_DISABLE;
	   end
	end
	
	/********** Xilinx FPGA Block RAM : Dual port RAM **********/
	//利用赛灵思FPGA的块RAM模块
	x_s3e_dpram x_s3e_dpram (
        /********** Port A : IF stage **********/
        .clka  (clk),        
        .addra (if_spm_addr),
        .dia  (if_spm_wr_data),         
        .wea   (wea),       
        .doa (if_spm_rd_data),  
        /********** Port B : MEM stage **********/
        .clkb  (clk),        
        .addrb (mem_spm_addr),      
        .dib  (mem_spm_wr_data), 
        .web   (web),      
        .dob (mem_spm_rd_data) 
    );
	
endmodule
//FPGA的块RAM模块
/********** Global header **********/
`include "nettype.vh"
`include "stddef.vh"
`include "global_config.vh"

/********** Local header **********/
`include "spm.vh"

/********** Module **********/
module x_s3e_dpram (
	/********** Port A **********/
	input  wire				   clka,  // Clock
	input  wire [`SpmAddrBus]  addra, // Address
	input  wire [`WordDataBus] dina,  // Write data
	input  wire				   wea,	  // Write enable
	output reg	[`WordDataBus] douta, // Read data
	/********** Port B **********/
	input  wire				   clkb,  // Clock
	input  wire [`SpmAddrBus]  addrb, // Address
	input  wire [`WordDataBus] dinb,  // Write data
	input  wire				   web,	  // Write enable
	output reg	[`WordDataBus] doutb  // Read data
);

//`define SPM_DEPTH  4096	 // SPM's depth
//`define WordDataBus			31:0	 	 // Data bus

	/********** Memory **********/
	reg [`WordDataBus] mem [0:`SPM_DEPTH-1];

	/********** Memory access Port A **********/
	always @(posedge clka) begin
		// Read access
		if ((web == `ENABLE) && (addra == addrb)) begin
			douta	  <= #1 dinb;
		end else begin
			douta	  <= #1 mem[addra];
		end
		// Write access
		if (wea == `ENABLE) begin
			mem[addra]<= #1 dina;
		end
	end

	/********** Memory access (Port B) **********/
	always @(posedge clkb) begin
		// Read access
		if ((wea == `ENABLE) && (addrb == addra)) begin
			doutb	  <= #1 dina;
		end else begin
			doutb	  <= #1 mem[addrb];
		end
		// Write access
		if (web == `ENABLE) begin
			mem[addrb]<= #1 dinb;
		end
	end
endmodule

/*****************************************************/
/****************************************************/
端口定义:

IF阶段操作:取指令,并决定下一条PC寄存器的内容。
IF阶段由流水线寄存器与总线接口组成。
1.bus_if 总线接口
    /********** Clock & Reset **********/
	input  wire				   clk,			  
	input  wire				   reset,		   
	/********** Pipeline control signal **********/
	input  wire				   stall,          //流水线延迟信号		   
	input  wire				   flush,		  //流水线刷新信号
	output reg				   busy,		 //流水线总线忙信号
	/********** CPU interface **********/
	input  wire [`WordAddrBus] addr,		  //位宽30
	input  wire				   as_,			   // Address enable
	input  wire				   rw,			   // Read/Write
	input  wire [`WordDataBus] wr_data,		   //位宽32
	output reg	[`WordDataBus] rd_data,		   //数据输出口,位宽32
	/********** SPM interface **********/
	input  wire [`WordDataBus] spm_rd_data,	   // Read data 32
	output wire [`WordAddrBus] spm_addr,	   // Address 30
	output reg				   spm_as_,		   // Address strobe
	output wire				   spm_rw,		   // Read/Write
	output wire [`WordDataBus] spm_wr_data,	   // Write data 32
	/********** Bus interface **********/
	input  wire [`WordDataBus] bus_rd_data,	   // Read data 32
	input  wire				   bus_rdy_,	   // Ready
	input  wire				   bus_grnt_,	   // Bus grant
	output reg				   bus_req_,	   // Bus request
	output reg	[`WordAddrBus] bus_addr,	   // Address 30
	output reg				   bus_as_,		   // Address strobe
	output reg				   bus_rw,		   // Read/Write
	output reg	[`WordDataBus] bus_wr_data	   // Write data 32

四个状态机,总线接口由俩个部分组成,一部分是控制内存访问的组合电路,另一部分是控制总线接口状态的时序电路。


2.if_reg
    /********** Clock & Reset **********/
	input  wire				   clk,		  
	input  wire				   reset,	   
	/********** Fetch data **********/
	input  wire [`WordDataBus] insn,	   // Fetched instruction 32
	/********** Pipeline control signal **********/
	input  wire				   stall,	   
	input  wire				   flush,	   
	input  wire [`WordAddrBus] new_pc,	   // New program counter 位宽30
	input  wire				   br_taken,   // Branch taken 分支成立
	input  wire [`WordAddrBus] br_addr,	   // Branch address 分支目标地址 位宽30
	/********** IF/ID pipeline register **********/
	output reg	[`WordAddrBus] if_pc,	   // Program counter 位宽30
	output reg	[`WordDataBus] if_insn,	   // Instruction 指令 位宽32
	output reg				   if_en	   // Enable pipeline data 流水线数据有效标志位
   
   
   
3.if_stage
    /********** Clock & Reset **********/
	input  wire				   clk,			
	input  wire				   reset,		
	/********** SPM interface **********/
	input  wire [`WordDataBus] spm_rd_data, // Read data
	output wire [`WordAddrBus] spm_addr,	// Address
	output wire				   spm_as_,		// Address strobe
	output wire				   spm_rw,		// Read/Write
	output wire [`WordDataBus] spm_wr_data, // Write data
	/********** Bus interface **********/
	input  wire [`WordDataBus] bus_rd_data, // Read data
	input  wire				   bus_rdy_,	// Ready
	input  wire				   bus_grnt_,	// Bus grant
	output wire				   bus_req_,	// Bus request
	output wire [`WordAddrBus] bus_addr,	// Address
	output wire				   bus_as_,		//Address strobe
	output wire				   bus_rw,		// Read/Write
	output wire [`WordDataBus] bus_wr_data, // Write data
	/********** Pipeline control signal **********/
	input  wire				   stall,		// Stall
	input  wire				   flush,		// Flush
	input  wire [`WordAddrBus] new_pc,		// New program counter
	input  wire				   br_taken,	// Branch taken
	input  wire [`WordAddrBus] br_addr,		// Branch address
	output wire				   busy,		// Busy signal
	/********** IF/ID pipeline register **********/
	output wire [`WordAddrBus] if_pc,		// Program counter
	output wire [`WordDataBus] if_insn,		// Instruction
	output wire				   if_en		// Enable pipeline data
    
    

3.总线接口

使用状态机
在这里插入图片描述
代码如下:

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

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


module bus_if(
    /********** Clock & Reset **********/
	input  wire				   clk,			  
	input  wire				   reset,		   
	/********** Pipeline control signal **********/
	input  wire				   stall,          //流水线延迟信号		   
	input  wire				   flush,		  //流水线刷新信号
	output reg				   busy,		 //流水线总线忙信号
	/********** CPU interface **********/
	input  wire [`WordAddrBus] addr,		  //位宽30
	input  wire				   as_,			   // Address enable
	input  wire				   rw,			   // Read/Write
	input  wire [`WordDataBus] wr_data,		   //位宽32
	output reg	[`WordDataBus] rd_data,		   //数据输出口,位宽32
	/********** SPM interface **********/
	input  wire [`WordDataBus] spm_rd_data,	   // Read data 32
	output wire [`WordAddrBus] spm_addr,	   // Address 30
	output reg				   spm_as_,		   // Address strobe
	output wire				   spm_rw,		   // Read/Write
	output wire [`WordDataBus] spm_wr_data,	   // Write data 32
	/********** Bus interface **********/
	input  wire [`WordDataBus] bus_rd_data,	   // Read data 32
	input  wire				   bus_rdy_,	   // Ready
	input  wire				   bus_grnt_,	   // Bus grant
	output reg				   bus_req_,	   // Bus request
	output reg	[`WordAddrBus] bus_addr,	   // Address 30
	output reg				   bus_as_,		   // Address strobe
	output reg				   bus_rw,		   // Read/Write
	output reg	[`WordDataBus] bus_wr_data	   // Write data 32

    );
    /********** Internal signal **********/
	reg	 [`BusIfStateBus]	   state;		   // Status of bus interface 2
	reg	 [`WordDataBus]		   rd_buf;		   // Read buffer 32
	wire [`BusSlaveIndexBus]   s_index;		   // Bus slave index 3(从属有8个)

//`define BusSlaveIndexLoc   29:27
//生成总线从属索引
    assign s_index = addr[`BusSlaveIndexLoc];
    /**********输出的赋值*******************/
    assign spm_addr=addr;
    assign spm_rw =rw;
    assign spm_wr_data=wr_data;
    /***************1.内存访问控制****************/
    always@(*) 
    begin
    //代入初始值
    rd_data = `WORD_DATA_W'h0;
    spm_as_=`DISABLE_;
    busy = `DISABLE;
    /*总线接口状态*/
    /*	
    // Status
	`define BUS_IF_STATE_IDLE	 2'h0  // Idle
	`define BUS_IF_STATE_REQ	 2'h1  // Bus request
	`define BUS_IF_STATE_ACCESS	 2'h2  // Bus access
	`define BUS_IF_STATE_STALL	 2'h3  // Stall
	*/
    case(state)
        `BUS_IF_STATE_IDLE :begin   //空闲状态
            //内存访问,主要实现SPM和CPU之间的连接
            if((flush==`DISABLE)&&(as_==`ENABLE_))begin
            //开始内存访问操作,选择访问目标
           
                if(s_index == `BUS_SLAVE_1) begin//访问SPM   `define BUS_SLAVE_1		   1	
                  
                    if(stall ==`DISABLE) begin//检测延时是否发生,此时流水线非延迟
                       
                        spm_as_ =`ENABLE_;
                        if(rw==`READ) begin
                     
                            rd_data= spm_rd_data;//把SPM读取的数据输出到数据输出端口
                          
                        end
                    end
               end
               else begin
                    busy =`ENABLE;//SPM访问在一个周期就可以实现,如果不是SPM从属,则需要访问总线,使得总线busy
               end
            end
         end
         
         //请求总线
         `BUS_IF_STATE_REQ : begin
            busy=`ENABLE; //此时总线访问正在进行,总线忙信号有效
          end
          
         //访问总线
         `BUS_IF_STATE_ACCESS : begin
         //等待就绪信号
             if (bus_rdy_ == `ENABLE) begin //就绪信号使能时,总线访问介绍,当rw为读取信号时,
                if(rw==`READ) begin
                    rd_data=bus_rd_data;  //总线的读取信号输出给读取端口
                end
             end 
             else begin
                busy=`ENABLE; //当就绪信号无效时,说明总线访问正在进行,总线忙
             end
          end
          
          //延迟
        `BUS_IF_STATE_STALL : begin
            if(rw ==`READ) begin //等待延迟解除时,如果rw为读信号,因为总线访问已经结束,
                                //直接把缓存数据,输出给读取端口。并使得忙信号无效
                rd_data =rd_buf;
            end
        end
        
   endcase
  end
    
 /********** Control bus interface status **********/ 
 /****************2.总线接口控制*********************/
 always@(posedge clk , `RESET_EDGE reset) begin
        if(reset == `RESET_ENABLE) begin
        //异步复位
            state		<= #1 `BUS_IF_STATE_IDLE;
			bus_req_	<= #1 `DISABLE_;
			bus_addr	<= #1 `WORD_ADDR_W'h0;
			bus_as_		<= #1 `DISABLE_;
			bus_rw		<= #1 `READ;
			bus_wr_data <= #1 `WORD_DATA_W'h0;
			rd_buf		<= #1 `WORD_DATA_W'h0;
		end 
		else begin
		//总线接口状态,主要实现状态机的转变
		case(state)
		      `BUS_IF_STATE_IDLE	 : begin //空闲
                  if ((flush == `DISABLE) && (as_ == `ENABLE_)) begin 
                      if(s_index != `BUS_SLAVE_1) begin
                      state <= #1 `BUS_IF_STATE_REQ;
                      bus_req_ <= #1 `ENABLE_;
                      bus_addr <= #1 addr;
                      bus_rw <= #1 rw;
                      bus_wr_data <=wr_data;
                      end
                  end
              end
              //请求总线
             `BUS_IF_STATE_REQ: begin
             //等待总线许可
                 if(bus_grnt_==`ENABLE_)begin //获得总线使用权
                    state <= #1 `BUS_IF_STATE_ACCESS;
                    bus_as_ <= #1 `ENABLE_;
                 end
             end
             
             `BUS_IF_STATE_ACCESS : begin
                  bus_as_ <= #1 `DISABLE_;//地址选通无效
                  //等待就绪信号
                  if(bus_rdy_ ==`ENABLE_) begin
                  //释放总线,信号数据初始化
                        bus_req_ <= #1 `DISABLE_;
                        bus_addr	<= #1 `WORD_ADDR_W'h0;
                        bus_rw		<= #1 `READ;
                        bus_wr_data <= #1 `WORD_DATA_W'h0;
                        //保存读取到的数据
                       if (bus_rw==`READ)begin
                            rd_buf <= #1 bus_rd_data;
                       end
                       if(stall == `ENABLE)begin //发生延迟
                            state <= #1 `BUS_IF_STATE_STALL;
                       end else begin
                            state <= #1  `BUS_IF_STATE_IDLE;
                       end
                  end
               end
             `BUS_IF_STATE_STALL : begin //延迟
             //检测延时是否发生
                    if(stall ==`DISABLE) begin
                        state <= #1 `BUS_IF_STATE_IDLE;
                    end
              end
              
             
         endcase
        end
end
endmodule

4.IF阶段流水线寄存器

实现取指,并决定下一条PC寄存器的内容

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

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

module if_reg(
    /********** Clock & Reset **********/
	input  wire				   clk,		  
	input  wire				   reset,	   
	/********** Fetch data **********/
	input  wire [`WordDataBus] insn,	   // Fetched instruction 32
	/********** Pipeline control signal **********/
	input  wire				   stall,	   
	input  wire				   flush,	   
	input  wire [`WordAddrBus] new_pc,	   // New program counter 位宽30
	input  wire				   br_taken,   // Branch taken 分支成立
	input  wire [`WordAddrBus] br_addr,	   // Branch address 分支目标地址 位宽30
	/********** IF/ID pipeline register **********/
	output reg	[`WordAddrBus] if_pc,	   // Program counter 位宽30
	output reg	[`WordDataBus] if_insn,	   // Instruction 指令 位宽32
	output reg				   if_en	   // Enable pipeline data 流水线数据有效标志位
    );
    /*************流水线寄存器*********************/
    always @(posedge clk or `RESET_EDGE reset) begin
        if(reset == `RESET_ENABLE) begin
           //异步复位
           //`define RESET_VECTOR		 30'h0 // Reset header
           //`define ISA_NOP			   32'h0
           if_pc   <= #1 `RESET_VECTOR;
           if_insn <= #1 `ISA_NOP;
           if_en   <= #1  `DISABLE;
         end else 
             begin
             //更新流水线寄存器
             if (stall == `DISABLE) begin
               
                 if (flush ==`ENABLE) begin //刷新流水线,PC值更新
                
                    if_pc   <= #1 new_pc;
                    if_insn <= #1 `ISA_NOP;
                    if_en   <= #1 `DISABLE;
                    end
                 else if (br_taken ==`ENABLE) begin//PC更新为分支目标地址
                     if_pc   <= #1 br_addr;
                     if_insn <= #1 insn;
                     if_en   <= #1 `ENABLE;
                    end
                  else begin
                     if_pc   <= #1 if_pc + 1'd1;
                     if_insn <= #1 insn;
                     if_en   <= #1 `ENABLE;
                     end
              end
              end
         end 
endmodule

5.TOP模块,连接各个模块

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

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

/********** Local header **********/
`include "cpu.vh"


module if_stage(
    /********** Clock & Reset **********/
	input  wire				   clk,			
	input  wire				   reset,		
	/********** SPM interface **********/
	input  wire [`WordDataBus] spm_rd_data, // Read data
	output wire [`WordAddrBus] spm_addr,	// Address
	output wire				   spm_as_,		// Address strobe
	output wire				   spm_rw,		// Read/Write
	output wire [`WordDataBus] spm_wr_data, // Write data
	/********** Bus interface **********/
	input  wire [`WordDataBus] bus_rd_data, // Read data
	input  wire				   bus_rdy_,	// Ready
	input  wire				   bus_grnt_,	// Bus grant
	output wire				   bus_req_,	// Bus request
	output wire [`WordAddrBus] bus_addr,	// Address
	output wire				   bus_as_,		//Address strobe
	output wire				   bus_rw,		// Read/Write
	output wire [`WordDataBus] bus_wr_data, // Write data
	/********** Pipeline control signal **********/
	input  wire				   stall,		// Stall
	input  wire				   flush,		// Flush
	input  wire [`WordAddrBus] new_pc,		// New program counter
	input  wire				   br_taken,	// Branch taken
	input  wire [`WordAddrBus] br_addr,		// Branch address
	output wire				   busy,		// Busy signal
	/********** IF/ID pipeline register **********/
	output wire [`WordAddrBus] if_pc,		// Program counter
	output wire [`WordDataBus] if_insn,		// Instruction
	output wire				   if_en		// Enable pipeline data
    );
    /********** Internal signal **********/
	wire [`WordDataBus]		   insn;		// Fetched instruction
    /********** Bus interface **********/
	bus_if bus_if (
		/********** Clock & Reset **********/
		.clk		 (clk),					
		.reset		 (reset),				
		/********** Pipeline control signal **********/
		.stall		 (stall),				
		.flush		 (flush),				
		.busy		 (busy),				
		/********** CPU interface **********/
		.addr		 (if_pc),				
		.as_		 (`ENABLE_),		//每个周期都需要取指,as信号之间挂高	
		.rw			 (`READ),			//IF只要READ不需要WRITE	
		.wr_data	 (`WORD_DATA_W'h0),	//IF只要READ不需要WRITE	
		.rd_data	 (insn),				
		/********** Scratchpad memory interface **********/
		.spm_rd_data (spm_rd_data),			
		.spm_addr	 (spm_addr),			
		.spm_as_	 (spm_as_),				
		.spm_rw		 (spm_rw),				
		.spm_wr_data (spm_wr_data),			
		/********** Bus interface **********/
		.bus_rd_data (bus_rd_data),			
		.bus_rdy_	 (bus_rdy_),			
		.bus_grnt_	 (bus_grnt_),			
		.bus_req_	 (bus_req_),			
		.bus_addr	 (bus_addr),			
		.bus_as_	 (bus_as_),				
		.bus_rw		 (bus_rw),				
		.bus_wr_data (bus_wr_data)			
	);
	/********** IF stage pipeline register **********/
	if_reg if_reg (
		/********** Clock & Reset **********/
		.clk		 (clk),					
		.reset		 (reset),				
		/********** Fetch data **********/
		.insn		 (insn),				// Fetched instruction
		/********** Pipeline control signal **********/
		.stall		 (stall),				
		.flush		 (flush),				
		.new_pc		 (new_pc),				
		.br_taken	 (br_taken),			
		.br_addr	 (br_addr),				
		/********** IF/ID pipeline register **********/
		.if_pc		 (if_pc),				
		.if_insn	 (if_insn),				
		.if_en		 (if_en)				
	);


    
endmodule

6.仿真

仿真思路:
IF阶段:输入PC地址,在对应内存拿到指令,输出。
观察TOP模块的连接端口,
先是bus_if总线接口,实现CPU和SPM的连接,实现取出指令。
然后是if的流水线寄存器,给PC输出指令。

我们先利用if寄存器,给出PC(这边指向SPM内存),PC值输入给bus_if接口addr,其中s_index将会取出addr高3位,连接到SPM中,将spm中的rd_dat赋值给rd_data输出;而rd_data将会和指令数据连接insn,最后由if寄存器输出对应的指令(if_insn)
代码如下:

`include"nettype.vh"
`include"stddef.vh"
`include"global_config.vh"
`include"bus.vh"
`include"rom.vh"

module If_test(

    );
    //端口定义
      /********** Clock & Reset **********/
	  reg				   clk;			
	  reg				   reset;		
	 /********** SPM interface **********/
	  reg [`WordDataBus] spm_rd_data; // Read data
	 wire [`WordAddrBus] spm_addr;	// Address
	 wire				   spm_as_;		// Address strobe
	 wire				   spm_rw;		// Read/Write
	 wire [`WordDataBus] spm_wr_data; // Write data
	/********** Bus interface **********/
	  wire [`WordDataBus] bus_rd_data; // Read data
	  wire				   bus_rdy_;	// Ready
	  reg				   bus_grnt_;	// Bus grant
	 wire				   bus_req_;	// Bus request
	 wire [`WordAddrBus] bus_addr;	// Address
	 wire				   bus_as_;		//Address strobe
	 wire				   bus_rw;		// Read/Write
	 wire [`WordDataBus] bus_wr_data; // Write data
	/********** Pipeline control signal **********/
	  reg				   stall;		// Stall
	  reg				   flush;		// Flush
	  reg [`WordAddrBus] new_pc;		// New program counter
	  reg				   br_taken;	// Branch taken
	  reg [`WordAddrBus] br_addr;		// Branch address
	 wire				   busy;		// Busy signal
	/********** IF/ID pipeline register **********/
	 wire [`WordAddrBus] if_pc;		// Program counter
	 wire [`WordDataBus] if_insn;		// Instruction
	 wire				   if_en;		// Enable pipeline data
	 wire  [`WordDataBus]		   insn;
	   integer i;
    parameter STEP=100;
    
    always#(STEP/2)begin
    clk<=~clk;
    end
    
    //实例化
    bus_if bus_if (
		/********** Clock & Reset **********/
		.clk		 (clk),					
		.reset		 (reset),				
		/********** Pipeline control signal **********/
		.stall		 (stall),				
		.flush		 (flush),				
		.busy		 (busy),				
		/********** CPU interface **********/
		.addr		 (if_pc),				
		.as_		 (`ENABLE_),		//每个周期都需要取指,as信号之间挂高	
		.rw			 (`READ),			//IF只要READ不需要WRITE	
		.wr_data	 (`WORD_DATA_W'h0),	//IF只要READ不需要WRITE	
		.rd_data	 (insn),				
		/********** Scratchpad memory interface **********/
		.spm_rd_data (spm_rd_data),			
		.spm_addr	 (spm_addr),			
		.spm_as_	 (spm_as_),				
		.spm_rw		 (spm_rw),				
		.spm_wr_data (spm_wr_data),			
		/********** Bus interface **********/
		.bus_rd_data (bus_rd_data),			
		.bus_rdy_	 (bus_rdy_),			
		.bus_grnt_	 (bus_grnt_),			
		.bus_req_	 (bus_req_),			
		.bus_addr	 (bus_addr),			
		.bus_as_	 (bus_as_),				
		.bus_rw		 (bus_rw),				
		.bus_wr_data (bus_wr_data)			
	);
	/********** IF stage pipeline register **********/
	if_reg if_reg (
		/********** Clock & Reset **********/
		.clk		 (clk),					
		.reset		 (reset),				
		/********** Fetch data **********/
		.insn		 (insn),				// Fetched instruction
		/********** Pipeline control signal **********/
		.stall		 (stall),				
		.flush		 (flush),				
		.new_pc		 (new_pc),				
		.br_taken	 (br_taken),			
		.br_addr	 (br_addr),				
		/********** IF/ID pipeline register **********/
		.if_pc		 (if_pc),				
		.if_insn	 (if_insn),				
		.if_en		 (if_en)				
	);
    //测试

     initial begin
    #10 begin
    clk<=1;
    reset<=`RESET_ENABLE;
    end
    #(STEP*3/4)
    #STEP begin
    reset<=`RESET_DISABLE;
    #STEP
    stall <=`DISABLE;
    
    #STEP
     new_pc<={{3'b001},{27{1'b0}}};
     flush<=`ENABLE;
   
    #STEP
     flush<=`DISABLE;
     
     
     #STEP
    
    spm_rd_data <= 32'hffff_ffff;

      end
    #STEP
    $finish;
    
  end
    
endmodule

仿真结果:
通过newpc刷新IF流水线,这时PC指向SPM地址,bus_if模块中CPU将取出SPM的数据,输出给if流水线寄存器。
SPM的数据输出给insn
仿真完成
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值