MIPS多周期CPU设计之使用时钟上升沿触发PC模块的实现方案
来源:互联网 发布:get it和got it 编辑:程序博客网 时间:2024/05/28 09:31
请勿转载,本人对该文章保留有所有权利,如果需要转载请联系gavingog@qq.com,经本人同意后才可转载
- 像上一篇博客MIPS多周期CPU设计所说的那样,如果我们要实现使用CLK时钟上升沿来触发PC模块的话要怎么解决呢?这次这篇博客就分析这一个问题。
- 首先第一点我们要明确时钟上升沿是同时作用于控制模块和PC模块的,所以如果等到IF阶段时钟上升沿来了,接着控制模块再发出PCWre的信号的话是完全没有作用的,因为这个时候在PC模块的时钟上升沿已经过去了,因此也就检测不到这个控制信号了。
- 接着如果要解决这个问题的话,在上一篇博客中我的解决方法是不使用上升沿触发PC模块,这是第一个方法;而在这里的话我们介绍第二种方案:可以通过在IF阶段的前一个阶段就发出PCWre控制信号,也就是aWB,cWB, (MEM && opcode==sw), ID(opcode != halt)这四种情况下置PCWre,而在IF阶段就把PCWre复位,这样子就可以正常检测到了时钟上升沿的到来了。
- 最后我们在这里只需要更改的有三个地方:ouputFunc模块,PC模块和RegFile模块(RegFile模块更改是为了解决下个时钟上升沿才会写回数据的bug)。
控制信号的改变(看红色的信号)
OutputFunc模块的更改代码
`timescale 1ns / 1ps// 输出函数模块module OutputFunc(state, opcode, zero, PCWre, InsMemRW, IRWre, WrRegData, RegWre, ALUSrcB, DataMemRW, ALUM2Reg, ExtSel, RegOut, PCSrc, ALUOp); input [2:0]state; input [5:0]opcode; input zero; output reg PCWre, InsMemRW, IRWre, WrRegData, RegWre, ALUSrcB, DataMemRW, ALUM2Reg; output reg[1:0]ExtSel, RegOut, PCSrc; output reg[2:0]ALUOp; parameter [2:0] IF = 3'b000, // IF状态 ID = 3'b001, // ID状态 aEXE = 3'b110, // add等指令的EXE状态 bEXE = 3'b101, // beq指令的EXE状态 cEXE = 3'b010, // sw,lw指令的EXE状态 MEM = 3'b011, // MEM状态 aWB = 3'b111, //add等指令的WB状态 cWB = 3'b100; // lw指令的WB状态 parameter [5:0] addi = 6'b000010, ori = 6'b010010, sll = 6'b011000, add = 6'b000000, sub = 6'b000001, move = 6'b100000, slt = 6'b100111, sw = 6'b110000, lw = 6'b110001, beq = 6'b110100, j = 6'b111000, jr = 6'b111001, Or = 6'b010000, And = 6'b010001, jal = 6'b111010, halt = 6'b111111; always @(state) begin // 对PCWre定值 ////////////////////// 注意这里更改了 ///////////////////// if (state == aWB || state == cWB || state == bEXE|| (state == MEM && opcode == sw)) PCWre = 1; else if (state == ID && (opcode == j || opcode == jal || opcode == jr)) PCWre = 1; else PCWre = 0; // 对InsMemRW定值 InsMemRW = 1; // 对IRWre定值 if (state == IF) IRWre = 1; else IRWre = 0; // 对WrRegData定值 if (state == aWB || state == cWB) WrRegData = 1; else WrRegData = 0; // 对RegWre定值 if (state == aWB || state == cWB || opcode == jal) RegWre = 1; else RegWre = 0; // 对ALUSrcB定值 if (opcode == addi || opcode == ori || opcode == sll || opcode == sw || opcode == lw) ALUSrcB = 1; else ALUSrcB = 0; // 对DataMemRW定值 if (state == MEM && opcode == sw) DataMemRW = 1; else DataMemRW = 0; // 对ALUM2Reg定值 if (state == cWB) ALUM2Reg = 1; else ALUM2Reg = 0; // 对ExtSel定值 if (opcode == ori) ExtSel = 2'b01; else if (opcode == sll) ExtSel = 2'b00; else ExtSel = 2'b10; // 对RegOut定值 if (opcode == jal) RegOut = 2'b00; else if (opcode == addi || opcode == ori || opcode == lw) RegOut = 2'b01; else RegOut = 2'b10; // 对PCSrc定值 case(opcode) j: PCSrc = 2'b11; jal: PCSrc = 2'b11; jr: PCSrc = 2'b10; beq: begin if (zero) PCSrc = 2'b01; else PCSrc = 2'b00; end default: PCSrc = 2'b00; endcase // 对ALUOp定值 case(opcode) sub: ALUOp = 3'b001; Or: ALUOp = 3'b101; And: ALUOp = 3'b110; ori: ALUOp = 3'b101; slt: ALUOp = 3'b010; sll: ALUOp = 3'b100; beq: ALUOp = 3'b001; default: ALUOp = 3'b000; endcase // 防止在IF阶段写数据 if (state == IF) begin RegWre = 0; DataMemRW = 0; end endendmodule
PC模块的更改
`timescale 1ns / 1ps// PC模块module PC(clk, i_pc, pcWre, reset, o_pc, outside_pc); input wire clk, pcWre, reset; input wire [31:0] i_pc, outside_pc; output reg [31:0] o_pc; always @(posedge clk) begin // 这里有更改,使用上升沿触发 if (reset) begin o_pc = outside_pc; end else if (pcWre) begin o_pc = i_pc; end else if (!pcWre) begin //停机时候指令不变 o_pc = o_pc; end endendmodule
RegFile模块的更改
`timescale 1ns / 1ps// 寄存器组module RegFile (rs, rt, rd, i_data, we, clk, o_data_1, o_data_2); input [4:0] rs, rt, rd; input [31:0] i_data; input we, clk; output [31:0] o_data_1, o_data_2; reg [31:0] register [0:31]; initial begin register[0] = 0; // 只需要确定零号寄存器的值就好,$0恒等于0 end assign o_data_1 = register[rs]; assign o_data_2 = register[rt]; ///////////// 这里有更改,使用下降沿触发,否则会产生下个时钟周期上升沿才会更改寄存器值的bug,在我们的流水线CPU设计中也是在后半段才写数据的,所以这里应该没有问题 ////////////// always @(negedge clk) begin if ((rd != 0) && (we == 1)) begin // rd != 0 是确保零号寄存器不会改变的作用 register[rd] = i_data; end endendmodule
1 0
- MIPS多周期CPU设计之使用时钟上升沿触发PC模块的实现方案
- MIPS多周期CPU设计(Verilog)
- MIPS-单周期CPU设计
- MIPS单周期CPU设计(Verilog)
- CPU性能衡量参数-主频,MIPS,CPI,时钟周期,机器周期,指令周期
- CPU性能衡量参数-主频,MIPS,CPI,时钟周期,机器周期,指令周期
- CPU性能衡量参数-主频,MIPS,CPI,时钟周期,机器周期,指令周期
- CPU性能衡量参数-主频,MIPS,CPI,时钟周期,机器周期,指令周期
- CPU性能衡量参数-主频,MIPS,CPI,时钟周期,机器周期,指令周期
- 多周期cpu设计与实现
- 多周期CPU设计
- 多周期CPU设计
- Verilog实现单周期CPU(部分MIPS指令集的指令)
- cpu 时钟周期
- 时钟周期、CPU周期、指令周期
- 单周期CPU的设计
- (Verilog)多周期CPU设计
- cpu时钟频率和MIPS
- js 获取文本框中光标所在字符串索引位置
- GIT - 基本概念(对象,索引,提交)
- 【CodeForces】#621A - Wet Shark and Odd and Even(水)
- Spring定时任务之Quartz
- 如何将Qt窗口的内容转化为图片?
- MIPS多周期CPU设计之使用时钟上升沿触发PC模块的实现方案
- HDU 4496 并查集
- Android自动化测试-从入门到入门(3)Espresso入门
- delphi工作笔记利用indy10发送邮件
- Sqlite3常用的插入方法及性能测试
- [JZOJ3401]【GDOI2014模拟】Pty爬山
- TCP学习~~
- 【codeforces】-#621-AWet Shark and Odd and Even(n个数最大偶数和)
- PullToRefreshListView