RISC-V ALU 运算器 Verilog Quartus

名称:RISC-V ALU 运算器 Verilog Quartus

软件:Quartus

语言:Verilog

开发板/平台:Cyclone IV FPGA开发板

功能介绍

这是一个基于 Verilog 的 RISC-V 整数 ALU FPGA 验证工程。设计支持 32 位两个操作数和 5 位功能码输入,用户可在开发板上通过 8 位拨码开关逐字节设置数据,使用确认按键完成输入锁存,再按启动键执行一次运算。\n\n运算结果除了输出 32 位数据,还提供结果有效、加法进位、减法借位、有符号溢出和结果为零等状态标志,便于通过 LED 直接观察 ALU 的运算状态。结果会锁存到顶层寄存器,避免输入变化影响当前显示。\n\n六位七段数码管以十六进制显示结果,并通过动态扫描和流动窗口展示完整的 32 位数据。工程同时配套顶层 Testbench、按键驱动任务、自动检查逻辑及 ModelSim 脚本,适合学习 RISC-V ALU 结构、按键采样、边沿检测、状态锁存和 FPGA 外设显示控制。

运行环境

EDA 工具为 Quartus II 13.0 SP1,目标器件为 Cyclone IV E 系列 EP4CE6F17C8,主时钟为开发板 50 MHz 时钟。仿真使用 ModelSim SE-64 10.1c,工程文件包含 QPF、QSF、管脚约束、Verilog RTL、Testbench 和一键运行脚本。\n\n顶层显示参数默认 SCAN_DIV=50000、SHIFT_DIV=50000000,适用于 50 MHz 时钟下的板级动态扫描和约 1 秒流动移动;仿真时可使用较小参数,例如 SCAN_DIV=4、SHIFT_DIV=100。

设计思路

本设计面向 RISC-V 整数 ALU 的板级验证,将输入采集、算术逻辑运算、结果锁存和人机显示拆分为独立模块。用户通过 8 位拨码开关设置功能码或一个操作数的当前字节,再使用低电平有效按键逐段确认。输入模块分别保存功能码、src0 和 src1,并在所需字段全部确认后产生对应的有效标志,避免未完成输入时启动计算。\n\n核心 riscv_alu 采用组合逻辑支持 ADD、SUB、SLT、SLTU、AND、OR、XOR、SLL、SRL、SRA、MOV_A 和 MOV_B 等功能码。加法输出进位标志,减法输出借位标志,有符号加法产生溢出标志,所有合法运算均提供结果有效和零结果标志。顶层对启动按键进行两级同步和高到低边沿检测,只有功能码及两个操作数均有效时才锁存结果和标志,从而让显示内容保持稳定。\n\n显示模块接收锁存后的 32 位结果,以十六进制拆分为多个 nibble,通过动态扫描驱动六位低电平有效七段数码管,并在环形序列中移动显示窗口。SCAN_DIV 用于调节位扫描速度,SHIFT_DIV 用于调节约 1 秒一次的流动速度;仿真时可将两个参数设置为较小值以缩短观察时间。

模块结构

顶层模块为 alu_top,负责按键边沿检测、子模块连接、结果与标志锁存以及外部 LED/数码管接口。alu_key_input 将拨码开关和低电平有效按键转换为 alu_func、alu_src0、alu_src1 及对应 vld 信号;每个 32 位操作数由四个 8 位字节依次确认,四段完成后置有效。riscv_alu 根据功能码完成算术、逻辑、移位和比较运算,输出结果及进位、借位、溢出、零结果标志。alu_display 对锁存结果进行十六进制译码、六位动态扫描和环形流动显示。工程还包含 alu_top_tb、riscv_alu_tb 及 run_alu_top_tb.do 仿真文件。

开发板验证

工程已在 CX401 Cyclone IV FPGA 开发板上完成验证,使用 Quartus 的管脚分配约束连接 50 MHz 时钟、低电平复位、8 位拨码开关、功能确认按键、两个 32 位操作数的分字节确认按键以及启动按键。板上通过 LED0~LED4 指示结果有效、加法进位、减法借位、溢出和零结果,6 位低电平有效七段数码管显示锁存后的 32 位运算结果。操作时先复位,再依次确认功能码和两个操作数的 4 个字节,最后按下启动键锁存结果;数码管按约 1 秒的节奏进行十六进制流动显示。

RISC-V ALU 运算器 Verilog Quartus 开发板验证图片 上板CX401开发板 (2).jpg

RISC-V ALU 运算器 Verilog Quartus 开发板验证图片 上板CX401开发板 (1).jpg

演示视频

配套演示视频展示了 CX401 开发板上的实际操作流程和显示效果,包括拨码开关输入功能码、分字节确认两个 32 位操作数、按下启动键完成一次 ALU 运算,以及 LED 标志和六位七段数码管流动显示结果的过程。

仿真图/仿真说明/设计文档图片

工程配套设计说明覆盖系统架构、数据流、顶层锁存、按键输入、ALU 运算、数码管显示、上板操作、引脚分配和常见问题排查,并提供 RTL 结构、管脚分配、仿真图和模块说明。alu_top_tb 采用顶层驱动方式模拟拨码与按键输入,包含复位后重新计算场景,自动检查 LED 标志及七段数码管反解出的十六进制数据。run_alu_top_tb.do 通过 vlib、vlog 和 vsim 命令完成编译与全流程仿真。文档中的仿真与设计图片可用于配合代码理解信号时序、模块连接和显示过程。

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image1.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image10.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image11.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image12.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image2.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image3.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image4.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image5.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image6.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image7.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image8.png

RISC-V ALU 运算器 Verilog Quartus 设计文档图片 image9.png

部分代码

以下展示顶层模块 alu_top 的部分代码,完整源码请下载压缩包查看。

module alu_top #(
    parameter integer SCAN_DIV  = 32'd50000,     // 数码管位扫描分频
    parameter integer SHIFT_DIV = 32'd50000000   // 数码管流动显示分频(约 1 秒)
)(
    input        clk,               // 板上 50MHz 时钟
    input        rst_n,             // 低电平复位(key4)
    input  [7:0] sw_in,             // 8 位拨码开关输入(BM8~BM1)
    input        alu_func_key,      // 功能码确认按键(SW55)
	 input alu_src1_key0,//按键,按下低电平,用于确认alu_src1_i[7:0]  输入完成SW33
	 input alu_src1_key1,//按键,按下低电平,用于确认alu_src1_i[15:8] 输入完成SW36
	 input alu_src1_key2,//按键,按下低电平,用于确认alu_src1_i[23:16]输入完成SW39
	 input alu_src1_key3,//按键,按下低电平,用于确认alu_src1_i[31:24]输入完成SW42
	 input alu_src2_key0,//按键,按下低电平,用于确认alu_src2_i[7:0]  输入完成SW47
	 input alu_src2_key1,//按键,按下低电平,用于确认alu_src2_i[15:8] 输入完成SW49
	 input alu_src2_key2,//按键,按下低电平,用于确认alu_src2_i[23:16]输入完成SW50
	 input alu_src2_key3,//按键,按下低电平,用于确认alu_src2_i[31:24]输入完成SW53
    input        start_key,         // 启动 ALU 运算并锁存结果的按键(SW45)
    output       alu_rslt_vld_led,  // 结果有效标志 LED0
    output       alu_add_carry_led, // 加法进位标志 LED1
    output       alu_sub_borrow_led,// 减法借位标志 LED2
    output       alu_overflow_led,  // 溢出标志 LED3
    output       alu_zero_led,      // 结果为 0 标志 LED4
    output [5:0] bit_select,        // 数码管位选(低电平选中)
    output [7:0] seg_select         // 数码管段选(低电平点亮)
);

// 来自输入模块的功能码与两个操作数
wire [4:0]  alu_func;
wire        alu_func_vld;
wire [31:0] alu_src0;
wire        alu_src0_vld;
wire [31:0] alu_src1;
wire        alu_src1_vld;

// 来自 ALU 的运算结果及标志位
wire [31:0] alu_rslt;
wire        alu_rslt_vld;
wire        alu_add_carry;
wire        alu_sub_borrow;
wire        alu_overflow;
wire        alu_zero;

// 锁存后的结果与标志位(按下 start_key 后更新)
reg [31:0]  alu_rslt_latch;
reg         alu_rslt_vld_latch;
reg         alu_add_carry_latch;
reg         alu_sub_borrow_latch;
reg         alu_overflow_latch;
reg         alu_zero_latch;

// start_key 的两级打拍寄存器,用于做边沿检测
reg start_key_d0;
reg start_key_d1;

wire start_pulse;   // start_key 从高到低的一个脉冲,表示“按下了一次”

assign start_pulse = start_key_d1 & ~start_key_d0;

//==========================================================
//  子模块例化:按键/拨码输入处理
//==========================================================
alu_key_input u_alu_key_input(
    .clk            (clk),
    .rst_n          (rst_n),
    .sw_in          (sw_in),
    .alu_func_key   (alu_func_key),
    .alu_src1_key0  (alu_src1_key0),
    .alu_src1_key1  (alu_src1_key1),
    .alu_src1_key2  (alu_src1_key2),
    .alu_src1_key3  (alu_src1_key3),
    .alu_src2_key0  (alu_src2_key0),
    .alu_src2_key1  (alu_src2_key1),
    .alu_src2_key2  (alu_src2_key2),
    .alu_src2_key3  (alu_src2_key3),
    .alu_func_o     (alu_func),
    .alu_func_vld_o (alu_func_vld),
    .alu_src0_o     (alu_src0),
    .alu_src0_vld_o (alu_src0_vld),
    .alu_src1_o     (alu_src1),
    .alu_src1_vld_o (alu_src1_vld)
);

//==========================================================
//  子模块例化:核心 ALU 运算
//==========================================================
riscv_alu u_riscv_alu(
    .alu_func_i       (alu_func),
    .alu_func_vld_i   (alu_func_vld),
    .alu_src0_i       (alu_src0),
    .alu_src0_vld_i   (alu_src0_vld),
    .alu_src1_i       (alu_src1),
    .alu_src1_vld_i   (alu_src1_vld),
    .alu_rslt_o       (alu_rslt),
    .alu_rslt_vld_o   (alu_rslt_vld),
    .alu_add_carry_o  (alu_add_carry),
    .alu_sub_borrow_o (alu_sub_borrow),
    .alu_overflow_o   (alu_overflow),
    .alu_zero_o       (alu_zero)
);

//==========================================================
//  子模块例化:数码管显示
//  注意:这里给显示模块的是“锁存后的”结果,
//        所以按一次 start_key,显示就更新一次。
//==========================================================
alu_display #(
    .SCAN_DIV  (SCAN_DIV),
    .SHIFT_DIV (SHIFT_DIV)
) u_alu_display(
    .clk            (clk),
    .rst_n          (rst_n),
    .alu_rslt_i     (alu_rslt_latch),
    .alu_rslt_vld_i (alu_rslt_vld_latch),
    .bit_select     (bit_select),
    .seg_select     (seg_select)
);

//==========================================================
//  主时序逻辑:按下 start_key 后锁存一次 ALU 结果
//==========================================================
// ... 以下代码略,完整源码请下载压缩包查看

代码文件(付费下载)

📥 付费后此处显示完整工程压缩包下载链接。
1、代码文件需要付费后才可见。
2、支付问题请联系微信公众号客服。
3、优质Verilog/VHDL代码资源,所见即所得。
Verilog/VHDL资源下载 » RISC-V ALU 运算器 Verilog Quartus

注册为本站会员,充值100得150,详情咨询客服

目前为止共有 *** 位优秀的会员加入! 立刻加入会员