S SmartDocs
系列: RISC V Hardware verilog 104 行 · 更新于 2026-07-04

riscv_single_cycle.v

RISC_V_Hardware/verilog/rtl/riscv_single_cycle.v

// ============================================================
// riscv_single_cycle.v -- single-cycle RV32I CPU core
// Harvard-style: separate instruction / data memory ports.
// ============================================================
`timescale 1ns/1ps

module riscv_single_cycle (
    input  wire        clk,
    input  wire        rst_n,
    // instruction memory port
    output wire [31:0] imem_addr,
    input  wire [31:0] imem_data,
    // data memory port
    output wire        dmem_read,
    output wire        dmem_write,
    output wire [31:0] dmem_addr,
    output wire [2:0]  dmem_funct3,
    output wire [31:0] dmem_wdata,
    input  wire [31:0] dmem_rdata,
    // debug
    output wire [31:0] dbg_pc
);
    // ---------------- program counter ----------------
    reg  [31:0] pc;
    wire [31:0] pc_plus4 = pc + 32'd4;
    wire [31:0] pc_next;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) pc <= 32'b0;
        else        pc <= pc_next;
    end

    assign imem_addr = pc;
    assign dbg_pc    = pc;
    wire [31:0] instr = imem_data;

    // ---------------- decode fields ----------------
    wire [6:0] opcode = instr[6:0];
    wire [4:0] rd     = instr[11:7];
    wire [2:0] funct3 = instr[14:12];
    wire [4:0] rs1    = instr[19:15];
    wire [4:0] rs2    = instr[24:20];

    // ---------------- control ----------------
    wire       reg_write, alu_src, mem_read, mem_write;
    wire       branch, jump, jalr, alu_a_pc;
    wire [1:0] wb_sel;
    wire [3:0] alu_op;

    control u_control (
        .opcode(opcode), .funct3(funct3), .funct7b5(instr[30]),
        .reg_write(reg_write), .alu_src(alu_src), .wb_sel(wb_sel),
        .mem_read(mem_read), .mem_write(mem_write),
        .branch(branch), .jump(jump), .jalr(jalr),
        .alu_a_pc(alu_a_pc), .alu_op(alu_op)
    );

    // ---------------- register file ----------------
    wire [31:0] rs1_data, rs2_data, wb_data;

    regfile u_regfile (
        .clk(clk), .we(reg_write),
        .ra1(rs1), .ra2(rs2), .wa(rd), .wd(wb_data),
        .rd1(rs1_data), .rd2(rs2_data)
    );

    // ---------------- immediate ----------------
    wire [31:0] imm;
    imm_gen u_immgen (.instr(instr), .imm(imm));

    // ---------------- ALU ----------------
    wire [31:0] alu_a = alu_a_pc ? pc : rs1_data;
    wire [31:0] alu_b = alu_src  ? imm : rs2_data;
    wire [31:0] alu_y;
    wire        alu_zero;

    alu u_alu (.a(alu_a), .b(alu_b), .alu_op(alu_op), .y(alu_y), .zero(alu_zero));

    // ---------------- branch decision ----------------
    wire br_taken;
    branch_unit u_branch (.rs1(rs1_data), .rs2(rs2_data), .funct3(funct3), .taken(br_taken));

    wire take_branch = branch & br_taken;
    wire [31:0] branch_target = pc + imm;
    wire [31:0] jalr_target   = (rs1_data + imm) & ~32'b1;

    assign pc_next = jump        ? branch_target :
                     jalr        ? jalr_target   :
                     take_branch ? branch_target :
                                   pc_plus4;

    // ---------------- data memory port ----------------
    assign dmem_read   = mem_read;
    assign dmem_write  = mem_write;
    assign dmem_addr   = alu_y;
    assign dmem_funct3 = funct3;
    assign dmem_wdata  = rs2_data;

    // ---------------- write-back ----------------
    assign wb_data = (wb_sel == 2'b01) ? dmem_rdata :
                     (wb_sel == 2'b10) ? pc_plus4   :
                     (wb_sel == 2'b11) ? imm        :
                                         alu_y;
endmodule

相关文章