主要模块
顶级模块(top)
内存(dmem和imem)
寄存器文件(regfile)
算术逻辑单元(alu)
控制单元(controller)
数据通路(datapath)
大致块图
信号列表
module top(input logic clk_in1_p,
input logic clk_in1_n,
input logic reset,
output logic [7:0] led);
这是顶级模块(top),它是处理器的最外层接口。clk_in1_p 和 clk_in1_n 表示差分时钟信号输入,reset 是重置信号,用于初始化处理器状态;led 是输出信号,可能用来指示某些状态或用于调试。
完整块图
变量定义
logic [31:0] PC, Instr, ReadData;
logic [31:0] WriteData, DataAdr;
logic clk, MemWrite;
在顶级模块内部定义了一些逻辑向量,PC 代表程序计数器,Instr 是指令寄存器,ReadData 和 WriteData 用于数据的读取和写入。DataAdr 表示数据存储地址。clk 是内部时钟信号,MemWrite 是一个布尔标志,用于指示是否执行内存写操作
// instantiate processor and memories
clk_wiz_0 u_clk_wiz
(
// Clock out ports
.clk_out1(clk), // output clk_out1
// Clock in ports
.clk_in1_p(clk_in1_p), // input clk_in1_p
.clk_in1_n(clk_in1_n)); // input clk_in1_n
这里创建了一个时钟向导(clk_wiz_0)实例用于生成处理器所需的时钟信号。
riscvsingle rvsingle(clk, reset, PC, Instr, MemWrite, DataAdr, WriteData, ReadData,led);
imem imem(PC, Instr);
dmem dmem(clk, MemWrite, DataAdr, WriteData, ReadData);
endmodule
riscvsingle 是RISC-V处理器的主要实例,imem 是指令内存,dmem 是数据内存的实例。这些实例化允许这些模块在顶级模块中运作。
module riscvsingle(input logic clk, reset,
output logic [31:0] PCF,
input logic [31:0] Instr,
output logic MemWriteM,
output logic [31:0] ALUResultM, WriteDataM,
input logic [31:0] ReadDataM,
output logic [7:0] led);
RISC-V单周期处理器的核心实现,它包含所有设计的主要功能部分,比如指令解析、执行和存储器访问。
controller c(clk, reset,InstrD[6:0], InstrD[14:12], InstrD[30], ZeroE,flushE,
ImmSrcD,ALUSrcE,ResultSrcE0,PCSrcE,alucontrolE,
RegWriteM, MemWriteM,
ResultSrcW,RegWriteW
);
controller模块负责生成控制信号,指导数据路径如何响应指令。其参数分别对应时钟、复位信号、指令操作码、函数码、分支逻辑等。
datapath dp(clk, reset, ImmSrcD, ALUSrcE,ResultSrcE0,PCSrcE,alucontrolE,RegWriteM,
ResultSrcW, RegWriteW,ZeroE,flushE,PCF,InstrF,InstrD,ALUResultM, WriteDataM,ReadDataM,led);
datapath模块实现指令的执行路径。这包括从指令内存获取指令、指令解码、寄存器文件读写、以及算术逻辑单元(ALU)等操作。
module maindec(input logic [6:0] op,
output logic [1:0] ResultSrc,
output logic MemWrite,
output logic Branch, ALUSrc,
output logic RegWrite, Jump,
output logic [1:0] ImmSrc,
output logic [1:0] ALUOp);
// ...
endmodule
maindec模块根据操作码解码指令,生成如分支、跳转、寄存器写入等控制信号。
module aludec(input logic opb5,
input logic [2:0] funct3,
input logic funct7b5,
input logic [1:0] ALUOp,
output logic [2:0] ALUControl);
// ...
endmodule
aludec模块负责生成ALU的控制信号,指导ALU如何对操作数执行操作(如加法、减法、逻辑运算等)。
module datapath(input logic clk, reset,
// ...
endmodule
这里是datapath模块,它处理寄存器之间的数据移动,以及与ALU、内存的交互。
module hazard(
input logic [4: 0] rs1D,
input logic [4: 0] rs2D,
// ... (其余参数省略)
output logic stallF,
output logic stallD,
output logic flushD,
output logic flushE
);
// ... (模块内部实现)
endmodule
hazard模块负责检测并解决数据冒险问题。数据冒险是指当前指令需要读取的数据,还没有被前一条指令写回的情况。
举例来说,如果指令需要使用的寄存器数据还没有被前面的指令写回,那么流水线就需要插入停顿(stall)来等待需要的数据。模块内部的逻辑会检测流水线中各种可能的冒险情况,并产生相应的控制信号来处理。
module regfile(input logic clk,
input logic we3,
input logic [ 4:0] a1, a2, a3,
input logic [31:0] wd3,
output logic [31:0] rd1, rd2,
output logic [7:0] led);
// ... (模块内部实现)
endmodule
regfile表示寄存器文件,它提供对32个32位寄存器的读写操作。we3为写使能信号,a1和a2为读取寄存器的地址,a3和wd3用于写入数据。rd1和rd2为输出数据,led用做显示输出或者调试。
module adder(input [31:0] a, b,
output [31:0] y);
// ...
endmodule
adder是一个加法器模块,用于计算地址或者指令中的偏移。
module extend(input logic [31:7] instr,
input logic [1:0] immsrc,
output logic [31:0] immext);
// ...
endmodule
extend用于指令中立即数的扩展,根据实际操作类型扩展符号位。
module alu(input logic [31:0] a, b,
input logic [2:0] alucontrol,
output logic [31:0] result,
output logic zero);
// ...
endmodule
alu是算术逻辑单元模块,根据alucontrol控制信号的不同进行运算(例如加法、与运算、或运算等)并产生结果。
// 模块 flopr (寄存器)
module flopr #(parameter WIDTH = 8)
(input logic clk, reset,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= 0;
else q <= d;
endmodule
flopr模块是一个参数化的D-触发器,可以用来构建同步寄存器。在时钟的上升沿,如果reset信号为高,则输出q被清零;否则,输入d的值则会被传递到输出q。
// 模块 floprc (带清除功能的寄存器)
module floprc #(parameter WIDTH = 8)
(input clk, reset, clear,
input [WIDTH-1:0] d,
output reg [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else if (clear) q <= #1 0;
else q <= #1 d;
endmodule
floprc模块扩展了flopr,增加了一个clear信号。如果clear信号为高,不仅在复位期间,而且在时钟周期内任何时候,输出q都会被清零。
// 模块 flopenr (带使能信号的寄存器)
module flopenr #(parameter WIDTH = 8)
(input clk, reset,
input en,
input [WIDTH-1:0] d,
output reg [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else if (en) q <= #1 d;
endmodule
flopenr模块为寄存器增加了一个使能(en)信号。当en为高时,输入d的值会在时钟上升沿被加载到输出q;当en为低时,输出q保持不变。
// 模块 flopenrc (带使能和清除信号的寄存器)
module flopenrc #(parameter WIDTH = 8, parameter VALUE_0 = 32'b0)
(input clk, reset,
input en, clear,
input [WIDTH-1:0] d,
output reg [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 VALUE_0;
else if (clear) q <= #1 VALUE_0;
else if (en) q <= #1 d;
endmodule
flopenrc模块结合了使能和清除功能。在时钟上升沿,如果复位(reset)或清除(clear)信号为高,则输出q被设置为0或VALUE_0值;如果两者都低,则仅在使能(en)为高时,输入d的值才会传递给输出q。
// 模块 mux2 (2路选择器)
module mux2 #(parameter WIDTH = 8)
(input logic [WIDTH-1:0] d0, d1,
input logic s,
output logic [WIDTH-1:0] y);
assign y = s ? d1 : d0;
endmodule
mux2模块是一个简单的2输入多路选择器。根据选择信号s的值,输出y等于输入d0或d1。
// 模块 mux3 (3路选择器)
module mux3 #(parameter WIDTH = 8)
(input logic [WIDTH-1:0] d0, d1, d2,
input logic [1:0] s,
output logic [WIDTH-1:0] y);
assign y = s[1] ? d2 : (s[0] ? d1 : d0);
endmodule
mux3模块是一个3输入选择器。根据两位选择信号s的值,输出y等于输入d0、d1或d2中的一个。