好好学习,天天向上,一流范文网欢迎您!
当前位置: >> 报告 >> 汇报材料 内容页

抽象叙述就是寄存器传输级(32-n)(图)

ori是一条I型指令,指令格式如下图所示。

I类指令格式

ori指令的指令码是6'b001101,所以当处理器发现正在处理的指令的高6位是6'b001101时,就知道当前正在处理ori指令。

该指令的使用方法是:将指令中的16位立即数取符号扩展为32位,然后与索引为rs的通用寄存器的值进行逻辑“或”运算。 运算结果存储在索引为rt 的通用寄存器中。 这里需要说明以下两点。

(1) 无符号扩展

符号扩展是将n位立即数的最高位复制到扩展后的32位数据的高(32-n)位,无符号扩展是将所有的高(32-n)位置位扩展的 32 位数据为 0。

以指令中的16位立即数扩展为32位为例,16位立即数分别是0x8000和0x1000处符号扩展和无符号扩展的结果。

16 位立即数扩展示例

(2) 通用寄存器

在MIPS32指令集架构中,定义了32个通用寄存器$0-$31。 要使用某个通用寄存器,只需要给出相应的索引即可,该索引占用5位。 ori指令中的rs和rt是通用寄存器的索引。 例如:当rs为5'b00011时,表示通用寄存器$3。

流水线结构的建立

在流水线结构中。 信号在寄存器之间传递,每传递到一个电平都会引起相应的组合逻辑电路发生变化。 这种模型的抽象描述就是寄存器传输级(RTL:Register Transfer Level)。

管道的简单模型获取阶段的实现

取指令阶段从指令存储器中取指令。 同时。 PC值递增,准备取下一条指令,包括PC和IF/ID两个模块。

1.电脑模块

PC模块的作用是给出指令地址。

module pc_reg(
	input	wire	            clk,
	input  wire	            rst,
	output reg[`InstAddrBus]  pc
);
	always @ (posedge clk) begin
	   if (rst == `RstEnable) begin
		ce <= `ChipDisable;  // 复位的时候指令存储器禁用
	   end else begin
		ce <= `ChipEnable;   // 复位结束后,指令存储器使能
	   end
	end
	always @ (posedge clk) begin
	   if (ce == `ChipDisable) begin
		pc <= 32'h00000000;  // 指令存储器禁用的时候,PC为0
	   end else begin
	  	pc <= pc + 4'h4;     // 指令存储器使能的时候。PC的值每时钟周期加4
	   end
	end
endmodule

InstAddrBus宏表示指令地址线的宽度,这里定义为32,RstEnable宏表示复位信号有效寄存器传输级,定义为1'b1,即输入rst为高时,表示复位信号有效。

复位时,输出指令存储器使能信号为ChipDisable,表示指令存储器被禁止,其他时候输出指令存储器使能信号为ChipEnable,表示指令存储器被使能。

当禁用指令存储器时。 当启用指令存储器时,PC 的值保持为 0。 PC的值每一个时钟周期加4,表示下一条指令的地址。 由于一条指令是32位的,按照字节寻址,一条指令对应4个字节。 所以PC加4指向下一条指令的地址。

2.IF/ID模块

IF/ID模块的作用是暂时保存取指阶段得到的指令和对应的指令地址,在下一个时钟传递给译码阶段。

module if_id(
	input	wire	clk,
	input  wire	rst,
	
       //来自取指阶段的信号,当中宏定义InstBus表示指令宽度,为32
	input wire[`InstAddrBus]      if_pc,
	input wire[`InstBus]          if_inst,
       //相应译码阶段的信号
	output reg[`InstAddrBus]      id_pc,
	output reg[`InstBus]          id_inst  
	
);
	always @ (posedge clk) begin
	   if (rst == `RstEnable) begin
	      id_pc <= `ZeroWord;    // 复位的时候pc为0
	      id_inst <= `ZeroWord;  // 复位的时候指令也为0,实际就是空指令
	   end else begin
	      id_pc <= if_pc;        // 其余时刻向下传递取指阶段的值
	      id_inst <= if_inst;
	   end
	end
endmodule

从代码中可以看出,IF/ID模块只是在每个时钟周期的上升沿将fetch阶段的结果传送到decode阶段。

解码阶段的实现

此时我们的指令已经进入解码阶段。 在这个阶段,将对取出的指令进行解码:给出要执行的操作类型和操作涉及的操作数。 解码阶段包括三个模块:Regfile、ID和ID/EX。

1.regfile模块

Regfile模块实现了32个32位通用整数寄存器,可以同时读2个寄存器和写1个寄存器。

module regfile(
	input	wire	clk,
	input  wire	rst,
	
	// 写port
	input wire	              we,
	input wire[`RegAddrBus]	waddr,
	input wire[`RegBus]		wdata,
	
	// 读port1
	input wire	              re1,
	input wire[`RegAddrBus]    raddr1,
	output reg[`RegBus]        rdata1,
	
	// 读port2
	input wire          	re2,
	input wire[`RegAddrBus]	raddr2,
	output reg[`RegBus]        rdata2
);
/****************************************************************
***********          第一段:定义32个32位寄存器          *********
*****************************************************************/
reg[`RegBus]  regs[0:`RegNum-1];  
/****************************************************************
***********                第二段:写操作                *********
*****************************************************************/
	always @ (posedge clk) begin
	  if (rst == `RstDisable) begin
	    if((we == `WriteEnable) && (waddr != `RegNumLog2'h0)) begin
		regs[waddr] <= wdata;
	    end
	  end
	end
/****************************************************************
***********           第三段:读port1的读操作            *********
*****************************************************************/
	always @ (*) begin
	  if(rst == `RstEnable) begin
	    rdata1 <= `ZeroWord;
	  end else if(raddr1 == `RegNumLog2'h0) begin
	    rdata1 <= `ZeroWord;
	  end else if((raddr1 == waddr) && (we == `WriteEnable) 
	  	            && (re1 == `ReadEnable)) begin
	    rdata1 <= wdata;
	  end else if(re1 == `ReadEnable) begin
	    rdata1 <= regs[raddr1];
	  end else begin
	    rdata1 <= `ZeroWord;
	  end
	end
/****************************************************************
***********            第四段:读port2的读操作           *********
*****************************************************************/
	always @ (*) begin
	  if(rst == `RstEnable) begin
	    rdata2 <= `ZeroWord;
	  end else if(raddr2 == `RegNumLog2'h0) begin
	    rdata2 <= `ZeroWord;
	  end else if((raddr2 == waddr) && (we == `WriteEnable) 
	  	            && (re2 == `ReadEnable)) begin
	    rdata2 <= wdata;
	  end else if(re2 == `ReadEnable) begin
	    rdata2 <= regs[raddr2];
	  end else begin
	    rdata2 <= `ZeroWord;
	  end
	end
endmodule

(1) 第一段:定义了一个二维向量。 元素个数为RegNum,为32,每个元素的宽度为RegBus,也为32,所以这里定义了32个32位的寄存器。

(2)第二段:实现写寄存器操作。 当复位信号无效时(rst为RstDisable),写使能信号

No.we是有效的(we是WriteEnable),当写操作的目标寄存器不等于0时,写输入数据可以保存到目标寄存器。

之所以推断目的寄存器不为0,是因为MIPS32架构规定$0的值只能为0,所以不要写。 WriteEnable是定义在defines.v中的一个宏寄存器传输级,表示写使能信号有效。 这些宏定义的意思很明显,从名字就可以知道详细的意思。 因此,本书后面不再对宏定义进行解释,除非宏定义的含义不容易从名字上看清楚。

(3)第三段:实现第一个读寄存器端口,依次类推后面的步骤。

(4)第四段:实现第二个读寄存器端口。 详细过程与第三段类似,不再赘述。

注意:读寄存器操作是一个组合逻辑电路,即一旦要读取的输入寄存器地址raddr1或raddr2发生变化,就会立即给出新地址对应的寄存器的值,以保证所需要的在解码阶段获得值。 读寄存器的值,而写寄存器的操作是时序逻辑电路,写操作发生在时钟信号的上升沿。