Initial commit
This commit is contained in:
101
Hardware/LA32R.srcs/sim_1/new/cpu_tb.v
Normal file
101
Hardware/LA32R.srcs/sim_1/new/cpu_tb.v
Normal file
@@ -0,0 +1,101 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU Testbench
|
||||
** Module Name: cpu_tb
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** A self-checking testbench for the LA32R single-cycle CPU.
|
||||
** - Generates clock and reset signals.
|
||||
** - Instantiates the cpu_top module.
|
||||
** - The instruction_memory module (instantiated within cpu_top) will load
|
||||
** the machine code from "program.hex".
|
||||
** - Monitors and displays the state of the PC and register file.
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.01 - File Created
|
||||
** Additional Comments:
|
||||
** - Place this file and "program.hex" in the simulation directory.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module cpu_tb;
|
||||
|
||||
// --- 信号声明 (Signal Declarations) ---
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
// --- 实例化待测设计 (Instantiate the Design Under Test) ---
|
||||
cpu_top uut (
|
||||
.clk(clk),
|
||||
.rst(rst)
|
||||
);
|
||||
|
||||
// --- 时钟生成器 (Clock Generator) ---
|
||||
localparam CLK_PERIOD = 10; // 时钟周期为10ns (Clock period is 10ns)
|
||||
initial begin
|
||||
clk = 0;
|
||||
forever #(CLK_PERIOD / 2) clk = ~clk;
|
||||
end
|
||||
|
||||
// --- 仿真控制 (Simulation Control) ---
|
||||
initial begin
|
||||
// 1. 复位CPU (Reset the CPU)
|
||||
rst = 1;
|
||||
#(CLK_PERIOD * 2); // 保持复位2个周期 (Hold reset for 2 cycles)
|
||||
rst = 0;
|
||||
$display("------------------------------------------------------------");
|
||||
$display(" CPU Simulation Started. Reset is released. ");
|
||||
$display("------------------------------------------------------------");
|
||||
|
||||
// 2. 运行一段时间后停止仿真
|
||||
// Stop the simulation after a certain amount of time.
|
||||
// The test program has an infinite loop at the end,
|
||||
// so we need to manually stop the simulation.
|
||||
#500; // 运行500ns (Run for 500ns)
|
||||
|
||||
// 3. 打印最终的寄存器状态
|
||||
// Print the final state of the registers
|
||||
$display("\n------------------------------------------------------------");
|
||||
$display(" Simulation Finished. Final Register State: ");
|
||||
$display("------------------------------------------------------------");
|
||||
// 使用$display来显示寄存器的值。注意路径需要正确。
|
||||
// Use $display to show register values. Note the path must be correct.
|
||||
for (integer i = 0; i < 32; i = i + 1) begin
|
||||
// 检查寄存器值是否非零,以简化输出
|
||||
// Check if register value is non-zero to simplify output
|
||||
if (uut.u_reg_file.registers[i] != 32'h00000000) begin
|
||||
$display("Register R%0d: 0x%08h", i, uut.u_reg_file.registers[i]);
|
||||
end
|
||||
end
|
||||
$display("※Please note that registers with value zero are hidden.※");
|
||||
$display("------------------------------------------------------------");
|
||||
|
||||
$finish; // 结束仿真 (End simulation)
|
||||
end
|
||||
|
||||
// --- 监控和显示 (Monitoring and Display) ---
|
||||
// 在每个时钟周期的下降沿打印信息,确保所有信号稳定
|
||||
// Display info at the falling edge of the clock to ensure all signals are stable.
|
||||
always @(negedge clk) begin
|
||||
if (!rst) begin
|
||||
$display("Time: %0t ns | PC: 0x%08h | Instruction: 0x%08h | R4=0x%h R5=0x%h R6=0x%h",
|
||||
$time,
|
||||
uut.pc_out,
|
||||
uut.instr,
|
||||
uut.u_reg_file.registers[4],
|
||||
uut.u_reg_file.registers[5],
|
||||
uut.u_reg_file.registers[6]
|
||||
);
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
80
Hardware/LA32R.srcs/sources_1/new/alu.v
Normal file
80
Hardware/LA32R.srcs/sources_1/new/alu.v
Normal file
@@ -0,0 +1,80 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: alu
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This module implements the Arithmetic Logic Unit (ALU) for the LA32R CPU.
|
||||
**
|
||||
** [FIXED] The implementation of SLT now uses the $signed() system function
|
||||
** to correctly handle comparisons that could cause overflow, such as
|
||||
** comparing a positive and a negative number.
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.02 - Corrected SLT implementation using $signed().
|
||||
** Revision 0.01 - File Created
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
module alu (
|
||||
input wire [31:0] a, // 操作数 A (Operand A)
|
||||
input wire [31:0] b, // 操作数 B (Operand B)
|
||||
input wire [3:0] alu_op, // ALU 操作控制码 (ALU Operation Control Code)
|
||||
output reg [31:0] result, // 运算结果 (Result)
|
||||
output wire zero, // 零标志位 (Zero Flag)
|
||||
output wire lt // 小于标志位 (Less Than Flag for BLT)
|
||||
);
|
||||
|
||||
// 定义ALU操作码的参数,增强可读性
|
||||
// Define parameters for ALU operations to enhance readability
|
||||
localparam ALU_ADD = 4'b0000;
|
||||
localparam ALU_SUB = 4'b0001;
|
||||
localparam ALU_AND = 4'b0010;
|
||||
localparam ALU_OR = 4'b0011;
|
||||
localparam ALU_NOR = 4'b0100;
|
||||
localparam ALU_SLT = 4'b0101;
|
||||
localparam ALU_SLTU = 4'b0110;
|
||||
|
||||
// 减法结果的临时线网
|
||||
// Temporary wire for subtraction result
|
||||
wire [31:0] sub_result = a - b;
|
||||
|
||||
// [FIX] 使用$signed()进行稳健的有符号比较
|
||||
// [FIX] Use $signed() for robust signed comparison
|
||||
wire slt_res = ($signed(a) < $signed(b));
|
||||
|
||||
// 无符号比较
|
||||
// Unsigned comparison
|
||||
wire sltu_res = (a < b);
|
||||
|
||||
// 主组合逻辑: 根据alu_op计算结果
|
||||
// Main combinational logic: calculate result based on alu_op
|
||||
always @(*) begin
|
||||
case (alu_op)
|
||||
ALU_ADD: result = a + b; // 加法 (Addition)
|
||||
ALU_SUB: result = sub_result; // 减法 (Subtraction)
|
||||
ALU_AND: result = a & b; // 与 (AND)
|
||||
ALU_OR: result = a | b; // 或 (OR)
|
||||
ALU_NOR: result = ~(a | b); // 或非 (NOR)
|
||||
ALU_SLT: result = {31'b0, slt_res}; // 有符号小于比较 (Set on Less Than, Signed)
|
||||
ALU_SLTU: result = {31'b0, sltu_res}; // 无符号小于比较 (Set on Less Than, Unsigned)
|
||||
default: result = 32'hxxxxxxxx; // 默认情况,输出不定态 (Default case, output undefined)
|
||||
endcase
|
||||
end
|
||||
|
||||
// 零标志位输出: 当减法结果为0时置1,用于BEQ指令
|
||||
// Zero flag output: set to 1 when the subtraction result is zero, for BEQ instruction
|
||||
assign zero = (sub_result == 32'h00000000);
|
||||
|
||||
// 小于标志位输出: 用于BLT指令
|
||||
// Less Than flag output: for BLT instruction
|
||||
assign lt = slt_res;
|
||||
|
||||
endmodule
|
||||
166
Hardware/LA32R.srcs/sources_1/new/control_unit.v
Normal file
166
Hardware/LA32R.srcs/sources_1/new/control_unit.v
Normal file
@@ -0,0 +1,166 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: control_unit
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This is the main control unit for the single-cycle LA32R CPU. It decodes
|
||||
** the instruction's opcode and function fields to generate all necessary
|
||||
** control signals for the datapath.
|
||||
**
|
||||
** [FIXED] Restructured the case statement to correctly handle instructions
|
||||
** that share the same opcode, such as LD.W and ST.W.
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.02 - Corrected case statement logic for shared opcodes.
|
||||
** Revision 0.01 - File Created
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
module control_unit (
|
||||
input wire [31:0] instr, // 指令输入 (Instruction Input)
|
||||
input wire zero_flag, // 来自ALU的零标志位 (Zero flag from ALU)
|
||||
input wire lt_flag, // 来自ALU的小于标志位 (Less-than flag from ALU)
|
||||
|
||||
output reg reg_write_en, // 寄存器写使能 (Register Write Enable)
|
||||
output reg mem_to_reg, // 选择写回寄存器的数据源 (Selects data source for register write-back)
|
||||
output reg mem_write_en, // 存储器写使能 (Memory Write Enable)
|
||||
output reg alu_src, // 选择ALU的第二操作数源 (Selects ALU's second operand source)
|
||||
output reg src_reg, // 选择寄存器堆的第二读地址源 (Selects Register File's second read address source)
|
||||
output reg [2:0] ext_op, // 立即数扩展控制 (Immediate extender control)
|
||||
output reg [3:0] alu_op, // ALU操作控制 (ALU operation control)
|
||||
output wire pcsource // PC下一个地址来源选择 (PC next address source selection)
|
||||
);
|
||||
|
||||
// 提取指令中的关键字段
|
||||
// Extract key fields from the instruction
|
||||
wire [5:0] opcode = instr[31:26];
|
||||
wire [1:0] func2 = instr[21:20]; // for 3R-type per ISA document
|
||||
wire [4:0] func5 = instr[19:15]; // for 3R-type per ISA document
|
||||
wire [3:0] func4 = instr[25:22]; // for 2RI12-type
|
||||
|
||||
// 定义指令操作码 (Opcode Definitions)
|
||||
localparam OP_GROUP_00 = 6'b000000; // Contains 3R instructions
|
||||
localparam OP_ADDI_W = 6'b000010;
|
||||
localparam OP_LUI12I = 6'b000101;
|
||||
localparam OP_GROUP_0A = 6'b001010; // Contains LD.W, ST.W
|
||||
localparam OP_B = 6'b010100;
|
||||
localparam OP_BEQ = 6'b010110;
|
||||
localparam OP_BLT = 6'b011000;
|
||||
|
||||
// 定义ALU操作码 (ALU Operation Definitions)
|
||||
localparam ALU_ADD = 4'b0000;
|
||||
localparam ALU_SUB = 4'b0001;
|
||||
localparam ALU_AND = 4'b0010;
|
||||
localparam ALU_OR = 4'b0011;
|
||||
localparam ALU_NOR = 4'b0100;
|
||||
localparam ALU_SLT = 4'b0101;
|
||||
localparam ALU_SLTU = 4'b0110;
|
||||
|
||||
// 定义立即数扩展类型 (Immediate Extension Type Definitions)
|
||||
localparam EXT_SI12 = 3'b001;
|
||||
localparam EXT_SI16 = 3'b010;
|
||||
localparam EXT_UI20 = 3'b011;
|
||||
localparam EXT_SI26 = 3'b100;
|
||||
|
||||
// 主译码逻辑 (Main Decoding Logic)
|
||||
always @(*) begin
|
||||
// --- 控制信号默认值,防止生成锁存器 ---
|
||||
// Default values for control signals to prevent latches
|
||||
reg_write_en = 1'b0;
|
||||
mem_to_reg = 1'b0;
|
||||
mem_write_en = 1'b0;
|
||||
alu_src = 1'b0;
|
||||
src_reg = 1'b0;
|
||||
ext_op = 3'bxxx;
|
||||
alu_op = 4'bxxxx;
|
||||
|
||||
case (opcode)
|
||||
OP_GROUP_00: begin
|
||||
// Differentiate based on func2 field
|
||||
if (func2 == 2'b01) begin // This is a 3R-type arithmetic/logic instruction
|
||||
reg_write_en = 1'b1;
|
||||
alu_src = 1'b0; // B operand comes from register
|
||||
src_reg = 1'b0; // Second read address comes from rk field
|
||||
// Further decode based on func5
|
||||
case(func5)
|
||||
5'b00000: alu_op = ALU_ADD;
|
||||
5'b00010: alu_op = ALU_SUB;
|
||||
5'b00100: alu_op = ALU_SLT;
|
||||
5'b00101: alu_op = ALU_SLTU;
|
||||
5'b01000: alu_op = ALU_NOR;
|
||||
5'b01001: alu_op = ALU_AND;
|
||||
5'b01010: alu_op = ALU_OR;
|
||||
default: alu_op = 4'bxxxx;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
OP_ADDI_W: begin
|
||||
// ADDI.W has its own opcode
|
||||
reg_write_en = 1'b1;
|
||||
alu_src = 1'b1; // B operand comes from immediate
|
||||
ext_op = EXT_SI12;
|
||||
alu_op = ALU_ADD;
|
||||
end
|
||||
OP_LUI12I: begin
|
||||
reg_write_en = 1'b1;
|
||||
alu_src = 1'b1;
|
||||
mem_to_reg = 1'b0; // ALU result writes back
|
||||
ext_op = EXT_UI20;
|
||||
alu_op = ALU_ADD; // ALU adds immediate to zero
|
||||
end
|
||||
OP_GROUP_0A: begin
|
||||
// Differentiate LD.W and ST.W based on func4
|
||||
if (func4 == 4'b0010) begin // LD.W
|
||||
reg_write_en = 1'b1;
|
||||
mem_to_reg = 1'b1; // Data from memory writes back
|
||||
alu_src = 1'b1;
|
||||
ext_op = EXT_SI12;
|
||||
alu_op = ALU_ADD; // Calculate address
|
||||
end
|
||||
else if (func4 == 4'b0110) begin // ST.W
|
||||
mem_write_en = 1'b1;
|
||||
alu_src = 1'b1;
|
||||
src_reg = 1'b1; // Second read address comes from rd field
|
||||
ext_op = EXT_SI12;
|
||||
alu_op = ALU_ADD; // Calculate address
|
||||
end
|
||||
end
|
||||
OP_B: begin
|
||||
// Unconditional branch
|
||||
ext_op = EXT_SI26;
|
||||
end
|
||||
OP_BEQ: begin
|
||||
alu_src = 1'b0;
|
||||
src_reg = 1'b1; // Second read address comes from rd field
|
||||
ext_op = EXT_SI16;
|
||||
alu_op = ALU_SUB; // Compare
|
||||
end
|
||||
OP_BLT: begin
|
||||
alu_src = 1'b0;
|
||||
src_reg = 1'b1; // Second read address comes from rd field
|
||||
ext_op = EXT_SI16;
|
||||
alu_op = ALU_SUB; // Compare
|
||||
end
|
||||
default: begin
|
||||
// All signals keep their default values
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// PC下一个地址来源的逻辑
|
||||
// Logic for PC's next address source
|
||||
wire beq_cond = (opcode == OP_BEQ) && zero_flag;
|
||||
wire blt_cond = (opcode == OP_BLT) && lt_flag;
|
||||
wire b_cond = (opcode == OP_B);
|
||||
|
||||
assign pcsource = beq_cond || blt_cond || b_cond;
|
||||
|
||||
endmodule
|
||||
144
Hardware/LA32R.srcs/sources_1/new/cpu_top.v
Normal file
144
Hardware/LA32R.srcs/sources_1/new/cpu_top.v
Normal file
@@ -0,0 +1,144 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: cpu_top
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This is the top-level module of the single-cycle LA32R CPU. It instantiates
|
||||
** and connects all sub-modules including PC, memories, register file, ALU,
|
||||
** immediate extender, and the control unit. The connections follow the
|
||||
** datapath diagram provided in the course design guide.
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.01 - File Created
|
||||
** Additional Comments:
|
||||
** - This file integrates the entire design.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module cpu_top (
|
||||
input wire clk,
|
||||
input wire rst
|
||||
);
|
||||
|
||||
// --- 内部连线声明 (Internal Wire Declarations) ---
|
||||
wire [31:0] pc_out;
|
||||
wire [31:0] instr;
|
||||
wire [31:0] imm_ext;
|
||||
wire [31:0] read_data1;
|
||||
wire [31:0] read_data2;
|
||||
wire [31:0] alu_result;
|
||||
wire [31:0] mem_read_data;
|
||||
wire [31:0] write_back_data;
|
||||
wire [31:0] alu_b_operand;
|
||||
|
||||
wire [4:0] reg_write_addr;
|
||||
wire [4:0] reg_read_addr1;
|
||||
wire [4:0] reg_read_addr2;
|
||||
wire [4:0] reg_read_addr2_final;
|
||||
|
||||
// 控制信号
|
||||
// Control Signals
|
||||
wire reg_write_en;
|
||||
wire mem_to_reg;
|
||||
wire mem_write_en;
|
||||
wire alu_src;
|
||||
wire src_reg;
|
||||
wire pcsource;
|
||||
wire zero_flag;
|
||||
wire lt_flag;
|
||||
wire [2:0] ext_op;
|
||||
wire [3:0] alu_op;
|
||||
|
||||
|
||||
// --- 模块实例化 (Module Instantiation) ---
|
||||
|
||||
// PC (程序计数器)
|
||||
pc u_pc (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.pcsource (pcsource),
|
||||
.imm_ext (imm_ext),
|
||||
.pc_out (pc_out)
|
||||
);
|
||||
|
||||
// Instruction Memory (指令存储器)
|
||||
instruction_memory u_inst_mem (
|
||||
.addr (pc_out),
|
||||
.instr (instr)
|
||||
);
|
||||
|
||||
// Control Unit (控制单元)
|
||||
control_unit u_ctrl_unit (
|
||||
.instr (instr),
|
||||
.zero_flag (zero_flag),
|
||||
.lt_flag (lt_flag),
|
||||
.reg_write_en (reg_write_en),
|
||||
.mem_to_reg (mem_to_reg),
|
||||
.mem_write_en (mem_write_en),
|
||||
.alu_src (alu_src),
|
||||
.src_reg (src_reg),
|
||||
.ext_op (ext_op),
|
||||
.alu_op (alu_op),
|
||||
.pcsource (pcsource)
|
||||
);
|
||||
|
||||
// Immediate Extender (立即数扩展单元)
|
||||
imm_extender u_imm_ext (
|
||||
.instr (instr),
|
||||
.ext_op (ext_op),
|
||||
.imm_ext (imm_ext)
|
||||
);
|
||||
|
||||
// MUX for Register File's second read address (src_reg_mux)
|
||||
assign reg_read_addr2_final = src_reg ? instr[4:0] : instr[14:10];
|
||||
|
||||
// Register File (寄存器堆)
|
||||
register_file u_reg_file (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.reg_write_en (reg_write_en),
|
||||
.read_addr1 (instr[9:5]),
|
||||
.read_addr2 (reg_read_addr2_final),
|
||||
.write_addr (instr[4:0]),
|
||||
.write_data (write_back_data),
|
||||
.read_data1 (read_data1),
|
||||
.read_data2 (read_data2)
|
||||
);
|
||||
|
||||
// MUX for ALU's second operand (alu_src_mux)
|
||||
assign alu_b_operand = alu_src ? imm_ext : read_data2;
|
||||
|
||||
// ALU (算术逻辑单元)
|
||||
alu u_alu (
|
||||
.a (read_data1),
|
||||
.b (alu_b_operand),
|
||||
.alu_op (alu_op),
|
||||
.result (alu_result),
|
||||
.zero (zero_flag),
|
||||
.lt (lt_flag)
|
||||
);
|
||||
|
||||
// Data Memory (数据存储器)
|
||||
data_memory u_data_mem (
|
||||
.clk (clk),
|
||||
.mem_write_en (mem_write_en),
|
||||
.addr (alu_result),
|
||||
.write_data (read_data2), // ST.W指令的数据来自第二个读端口(rd)
|
||||
.read_data (mem_read_data)
|
||||
);
|
||||
|
||||
// MUX for write-back data (mem_to_reg_mux)
|
||||
assign write_back_data = mem_to_reg ? mem_read_data : alu_result;
|
||||
|
||||
|
||||
endmodule
|
||||
32
Hardware/LA32R.srcs/sources_1/new/data_memory.v
Normal file
32
Hardware/LA32R.srcs/sources_1/new/data_memory.v
Normal file
@@ -0,0 +1,32 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Data Memory Module
|
||||
*******************************************************************************/
|
||||
|
||||
module data_memory (
|
||||
input wire clk, // 时钟 (Clock)
|
||||
input wire mem_write_en, // 写使能 (Write Enable)
|
||||
input wire [31:0] addr, // 地址输入 (Address input)
|
||||
input wire [31:0] write_data, // 待写数据 (Write data)
|
||||
output wire [31:0] read_data // 读出数据 (Read data)
|
||||
);
|
||||
// 在FPGA中,这会综合成一个同步写的RAM
|
||||
// In an FPGA, this synthesizes into a synchronous-write RAM.
|
||||
|
||||
reg [31:0] mem [0:1023]; // 示例: 1KB数据空间 (Example: 1KB data space)
|
||||
|
||||
// 同步写
|
||||
// Synchronous write
|
||||
always @(posedge clk) begin
|
||||
if (mem_write_en) begin
|
||||
mem[addr[11:2]] <= write_data;
|
||||
end
|
||||
end
|
||||
|
||||
// 异步读
|
||||
// Asynchronous read
|
||||
assign read_data = mem[addr[11:2]];
|
||||
|
||||
endmodule
|
||||
|
||||
76
Hardware/LA32R.srcs/sources_1/new/imm_extender.v
Normal file
76
Hardware/LA32R.srcs/sources_1/new/imm_extender.v
Normal file
@@ -0,0 +1,76 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: imm_extender
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This module handles the sign/zero extension of immediate values found in
|
||||
** various instruction formats of the LA32R architecture. It generates a 32-bit
|
||||
** immediate value based on the instruction and the control signal `ext_op`.
|
||||
**
|
||||
** Supported Extensions:
|
||||
** - 12-bit signed immediate (si12) for ADDI.W, LD.W, ST.W
|
||||
** - 20-bit immediate (si20) for LUI12I.W (zero-extended low)
|
||||
** - 16-bit signed offset for BEQ, BLT
|
||||
** - 26-bit signed offset for B
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.01 - File Created
|
||||
** Additional Comments:
|
||||
** - This is a purely combinational logic module.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
module imm_extender (
|
||||
input wire [31:0] instr, // 32位指令输入 (32-bit instruction input)
|
||||
input wire [2:0] ext_op, // 扩展操作控制信号 (Extension operation control signal)
|
||||
output reg [31:0] imm_ext // 32位扩展后的立即数输出 (32-bit extended immediate output)
|
||||
);
|
||||
|
||||
// 定义立即数扩展类型的参数
|
||||
// Define parameters for immediate extension types
|
||||
localparam EXT_SI12 = 3'b001; // 12-bit signed immediate for I-type
|
||||
localparam EXT_SI16 = 3'b010; // 16-bit signed offset for branches
|
||||
localparam EXT_UI20 = 3'b011; // 20-bit immediate for LUI
|
||||
localparam EXT_SI26 = 3'b100; // 26-bit signed offset for jump
|
||||
|
||||
// 提取指令中不同格式的立即数
|
||||
// Extract immediate values from different instruction formats
|
||||
wire [11:0] si12 = instr[21:10];
|
||||
wire [15:0] si16 = instr[25:10];
|
||||
wire [19:0] si20 = instr[24:5];
|
||||
wire [25:0] si26 = {instr[9:0], instr[25:10]}; // B指令的offs[25:16]在[9:0], offs[15:0]在[25:10]
|
||||
|
||||
// 组合逻辑: 根据ext_op选择不同的扩展方式
|
||||
// Combinational logic: select extension method based on ext_op
|
||||
always @(*) begin
|
||||
case (ext_op)
|
||||
EXT_SI12:
|
||||
// 对si12进行符号位扩展
|
||||
// Sign-extend si12
|
||||
imm_ext = {{20{si12[11]}}, si12};
|
||||
EXT_SI16:
|
||||
// 对si16进行符号位扩展并左移两位
|
||||
// Sign-extend si16 and shift left by 2
|
||||
imm_ext = {{14{si16[15]}}, si16, 2'b00};
|
||||
EXT_UI20:
|
||||
// 对si20进行高位加载,低12位补0
|
||||
// Load si20 to high bits, pad low 12 bits with 0
|
||||
imm_ext = {si20, 12'b0};
|
||||
EXT_SI26:
|
||||
// 对si26进行符号位扩展并左移两位
|
||||
// Sign-extend si26 and shift left by 2
|
||||
imm_ext = {{4{si26[25]}}, si26, 2'b00};
|
||||
default:
|
||||
imm_ext = 32'hxxxxxxxx; // 默认情况,输出不定态
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
31
Hardware/LA32R.srcs/sources_1/new/instruction_memory.v
Normal file
31
Hardware/LA32R.srcs/sources_1/new/instruction_memory.v
Normal file
@@ -0,0 +1,31 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Instruction Memory Module
|
||||
*******************************************************************************/
|
||||
|
||||
module instruction_memory (
|
||||
input wire [31:0] addr, // 地址输入 (Address input)
|
||||
output wire [31:0] instr // 指令输出 (Instruction output)
|
||||
);
|
||||
// 指令存储器通常是只读的 (Instruction memory is typically read-only)
|
||||
// 在FPGA中,这会综合成一个ROM
|
||||
// In an FPGA, this synthesizes into a ROM.
|
||||
|
||||
// 仿真时,使用reg数组和$readmemh加载程序
|
||||
// For simulation, use a reg array and $readmemh to load the program.
|
||||
reg [31:0] mem [0:1023]; // 示例: 1024条指令空间 (Example: 1024 instruction space)
|
||||
|
||||
initial begin
|
||||
// 从文件中加载指令
|
||||
// Load instructions from a file.
|
||||
// 你需要创建一个名为 "program.hex" 的文件
|
||||
// You need to create a file named "program.hex".
|
||||
$readmemh("../../../../../Software/program.hex", mem);
|
||||
end
|
||||
|
||||
// 字节地址转换为字地址
|
||||
// Convert byte address to word address.
|
||||
assign instr = mem[addr[11:2]];
|
||||
|
||||
endmodule
|
||||
56
Hardware/LA32R.srcs/sources_1/new/pc.v
Normal file
56
Hardware/LA32R.srcs/sources_1/new/pc.v
Normal file
@@ -0,0 +1,56 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: pc
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This module implements the Program Counter (PC) and its update logic.
|
||||
** The PC is a 32-bit register that holds the address of the instruction
|
||||
** to be fetched. It updates on every clock cycle.
|
||||
**
|
||||
** Update Logic:
|
||||
** - If no branch/jump: PC_next = PC_current + 4
|
||||
** - If branch/jump taken: PC_next = Branch/Jump Target Address
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.01 - File Created
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
module pc (
|
||||
input wire clk, // 时钟 (Clock)
|
||||
input wire rst, // 复位 (Reset)
|
||||
input wire pcsource, // PC下一个地址来源选择 (PC next address source selection)
|
||||
input wire [31:0] imm_ext, // 来自立即数扩展单元的偏移量 (Offset from immediate extender)
|
||||
output reg [31:0] pc_out // 当前PC值 (Current PC value)
|
||||
);
|
||||
|
||||
wire [31:0] pc_plus_4;
|
||||
wire [31:0] pc_branch;
|
||||
wire [31:0] pc_next;
|
||||
|
||||
// PC寄存器
|
||||
// PC register
|
||||
always @(posedge clk or posedge rst) begin
|
||||
if (rst) begin
|
||||
pc_out <= 32'h00000000; // 复位到0地址
|
||||
end else begin
|
||||
pc_out <= pc_next;
|
||||
end
|
||||
end
|
||||
|
||||
// PC更新逻辑
|
||||
// PC update logic
|
||||
assign pc_plus_4 = pc_out + 32'd4;
|
||||
assign pc_branch = pc_out + imm_ext; // 偏移量已经左移两位
|
||||
|
||||
assign pc_next = pcsource ? pc_branch : pc_plus_4;
|
||||
|
||||
endmodule
|
||||
79
Hardware/LA32R.srcs/sources_1/new/register_file.v
Normal file
79
Hardware/LA32R.srcs/sources_1/new/register_file.v
Normal file
@@ -0,0 +1,79 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*******************************************************************************
|
||||
** Company: Nantong University
|
||||
** Engineer: あやせももこ
|
||||
**
|
||||
** Create Date: 2025-06-16
|
||||
** Design Name: LA32R Single Cycle CPU
|
||||
** Module Name: register_file
|
||||
** Project Name: Computer Architecture Course Design
|
||||
** Target Devices: Any FPGA
|
||||
** Tool Versions: Vivado 2018.1
|
||||
** Description:
|
||||
** This module implements the 32x32-bit Register File for the LA32R CPU.
|
||||
** It features two asynchronous read ports and one synchronous write port.
|
||||
** A defensive design is implemented to ensure R0 is always zero.
|
||||
**
|
||||
** Features:
|
||||
** - 32 general-purpose registers, each 32 bits wide.
|
||||
** - Asynchronous read: Read ports reflect content immediately.
|
||||
** - Synchronous write: Write operation occurs on the rising edge of the clock.
|
||||
** - R0 Hardwired to Zero: Cannot be written to, and reading it always returns 0.
|
||||
**
|
||||
** Revision:
|
||||
** Revision 0.01 - File Created
|
||||
** Additional Comments:
|
||||
** - Reset logic is included to initialize all registers to zero, which is good practice for simulation and synthesis.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
module register_file (
|
||||
input wire clk, // 时钟 (Clock)
|
||||
input wire rst, // 复位 (Reset)
|
||||
input wire reg_write_en, // 写使能 (Write Enable)
|
||||
input wire [4:0] read_addr1, // 读地址1 (Read Address 1)
|
||||
input wire [4:0] read_addr2, // 读地址2 (Read Address 2)
|
||||
input wire [4:0] write_addr, // 写地址 (Write Address)
|
||||
input wire [31:0] write_data, // 写数据 (Write Data)
|
||||
output wire [31:0] read_data1, // 读数据1 (Read Data 1)
|
||||
output wire [31:0] read_data2 // 读数据2 (Read Data 2)
|
||||
);
|
||||
|
||||
// 声明32个32位的寄存器阵列
|
||||
// Declare an array of 32 registers, each 32 bits wide.
|
||||
reg [31:0] registers[0:31];
|
||||
|
||||
integer i;
|
||||
|
||||
// 同步写操作 (时钟上升沿触发)
|
||||
// Synchronous write operation (triggered on the rising edge of the clock)
|
||||
always @(posedge clk or posedge rst) begin
|
||||
if (rst) begin
|
||||
// 复位时,将所有寄存器清零
|
||||
// On reset, clear all registers to zero.
|
||||
for (i = 0; i < 32; i = i + 1) begin
|
||||
registers[i] <= 32'b0;
|
||||
end
|
||||
end else if (reg_write_en) begin
|
||||
// 写使能有效时,执行写操作
|
||||
// When write enable is active, perform the write operation.
|
||||
// 防御性设计:确保不写入0号寄存器
|
||||
// Defensive design: ensure register R0 is not written to.
|
||||
if (write_addr != 5'd0) begin
|
||||
registers[write_addr] <= write_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// 异步读操作1
|
||||
// Asynchronous read port 1
|
||||
// 防御性设计:确保读取0号寄存器时返回0
|
||||
// Defensive design: ensure reading from R0 always returns zero.
|
||||
assign read_data1 = (read_addr1 == 5'd0) ? 32'b0 : registers[read_addr1];
|
||||
|
||||
// 异步读操作2
|
||||
// Asynchronous read port 2
|
||||
assign read_data2 = (read_addr2 == 5'd0) ? 32'b0 : registers[read_addr2];
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user