// 杂记 · 2025-04-18

初探Vivado:编写逆序交换32字存储器内容代码

1. 打开Vivado并创建新项目

  1. 启动Vivado:

    • 在Windows/Linux上,找到Vivado的快捷方式或运行vivado命令启动Vivado IDE。
    • Vivado启动后,进入“Tcl Console”和主界面。
  2. 创建新项目:

    • 点击主界面左侧的“Create Project”或在菜单栏选择 File > Project > New。
    • 在“New Project”向导中,点击“Next”。
    • Project Name:
      • 输入项目名称,例如memory_swap_project。
      • 选择项目保存路径,例如C:\Vivado_Projects\memory_swap_project。
      • 勾选“Create project subdirectory”(推荐)。
      • 点击“Next”。
    • Project Type:
      • 选择“RTL Project”,确保“Do not specify sources at this time”未勾选(稍后添加源文件)。
      • 点击“Next”。
    • Add Sources(稍后添加Verilog文件,这里可跳过):
      • 暂时点击“Next”,后续再添加源文件。
    • Add Constraints(可选):
      • 暂时跳过约束文件,点击“Next”。
    • Default Part:
      • 选择目标FPGA器件,例如:
        • Xilinx 7 Series:如xc7a100tcsg324-1(Artix-7,Nexys 4 DDR开发板常用)。
        • 使用“Search”功能,输入器件型号或选择开发板(如Nexys 4 DDR)。
      • 点击“Next”。
    • Finish:
      • 核对项目信息,点击“Finish”创建项目。
      • Vivado会生成项目目录并打开项目。

2. 添加Verilog源文件

  1. 创建Verilog模块:

    • 在Vivado主界面,点击左侧“Flow Navigator”中的“Add Sources”(或菜单 File > Add Sources)。
    • 选择“Add or create design sources”,点击“Next”。
    • 点击“Create File”:
      • File type:选择“Verilog”。
      • File name:输入memory_swap。
      • File location:保持默认(项目源文件目录)。
      • 点击“OK”,然后“Finish”。
    • Vivado会生成一个空的memory_swap.v文件并打开。
  2. 编写Verilog代码:

    • 将以下代码复制到memory_swap.v中:
    module memory_swap (
        input wire clk,              // 时钟输入
        input wire rst_n,            // 低电平有效复位
        input wire start,            // 启动信号
        output reg done              // 完成信号
    );
    
        // 存储器定义
        reg [7:0] mem [0:31];        // 32个8位字的存储器
        reg [4:0] i;                 // 循环计数器(5位,0到31)
        reg [7:0] temp;              // 临时存储交换数据
        reg state;                   // 状态机:0=空闲,1=交换中
    
        // 状态机和交换逻辑
        always @(posedge clk or negedge rst_n) begin
            if (!rst_n) begin
                // 复位状态
                i <= 0;
                state <= 0;
                done <= 0;
                // 初始化存储器(示例初始化为索引值)
                for (i = 0; i < 32; i = i + 1) begin
                    mem[i] <= i; // 填充0,1,2,...,31以便验证
                end
            end
            else begin
                case (state)
                    0: begin // 空闲状态
                        done <= 0;
                        i <= 0;
                        if (start) begin
                            state <= 1; // 启动交换
                        end
                    end
                    1: begin // 交换状态
                        if (i < 16) begin // 只需交换前16对
                            // 交换 mem[i] 和 mem[31-i]
                            temp <= mem[i];
                            mem[i] <= mem[31-i];
                            mem[31-i] <= temp;
                            i <= i + 1;
                        end
                        else begin
                            state <= 0;
                            done <= 1; // 交换完成
                        end
                    end
                endcase
            end
        end
    
    endmodule
    • 保存文件(Ctrl+S或 File > Save)。
  3. 检查语法:

    • 在“Flow Navigator”中,点击“Run Synthesis”或“Run Simulation”前的“RTL Analysis”检查代码语法。
    • 如果有语法错误,Vivado会在“Messages”窗口报告,修正后重新保存。

3. 创建测试平台(Testbench)

  1. 添加Testbench文件:

    • 再次点击“Add Sources”,选择“Add or create simulation sources”。
    • 点击“Create File”:
      • File type:Verilog。
      • File name:memory_swap_tb。
      • 点击“OK”,然后“Finish”。
    • Vivado生成memory_swap_tb.v并打开。
  2. 编写Testbench代码:

    • 复制以下测试平台代码到memory_swap_tb.v:
    `timescale 1ns / 1ps
    module memory_swap_tb;
    
        // 输入
        reg clk;
        reg rst_n;
        reg start;
        // 输出
        wire done;
    
        // 实例化设计模块
        memory_swap uut (
            .clk(clk),
            .rst_n(rst_n),
            .start(start),
            .done(done)
        );
    
        // 时钟生成(50MHz,周期20ns)
        initial begin
            clk = 0;
            forever #10 clk = ~clk;
        end
    
        // 激励信号
        initial begin
            // 初始化
            rst_n = 0;
            start = 0;
            #40; // 等待40ns
            rst_n = 1; // 释放复位
    
            // 启动交换
            #20;
            start = 1;
            #20;
            start = 0;
    
            // 等待完成
            wait(done == 1);
            #100;
    
            // 结束仿真
            $finish;
        end
    
        // 监视存储器内容(可选)
        initial begin
            $monitor("Time=%0t rst_n=%b start=%b done=%b mem[0]=%h mem[31]=%h",
                     $time, rst_n, start, done, uut.mem[0], uut.mem[31]);
        end
    
    endmodule
    • 保存文件。
  3. 设置Testbench:

    • 在“Flow Navigator”中,点击“Simulation > Simulation Settings”。
    • 确保“Simulation Set”中选择了memory_swap_tb作为顶层模块。
    • 在“Simulation”选项卡中,设置仿真时间(例如1000ns)。
    • 点击“OK”。

4. 运行仿真

  1. 启动仿真:

    • 在“Flow Navigator”中,点击“Run Simulation > Run Behavioral Simulation”。
    • Vivado会编译Verilog代码和Testbench,并打开仿真窗口。
  2. 查看波形:

    • 在仿真窗口的“Scope”面板,找到memory_swap_tb和uut(设计实例)。
    • 右键单击信号(如clk, rst_n, start, done),选择“Add to Wave Window”。
    • 手动添加存储器信号:
      • 在“Objects”面板,展开uut,找到mem数组。
      • 右键mem[0]到mem[31],选择“Add to Wave Window”。
    • 点击工具栏的“Run All”按钮(或输入run -all在Tcl Console)。
    • 波形窗口会显示信号变化。
  3. 验证结果:

    • 检查复位后mem[0]到mem[31]是否初始化为0, 1, 2, ..., 31。
    • 启动start信号后,观察mem[0]与mem[31]、mem[1]与mem[30]等是否正确交换。
    • 确认done信号在交换完成后变为1。
    • 在“Tcl Console”或波形中,验证存储器内容是否逆序(例如,mem[0]=31, mem[1]=30, …, mem[31]=0)。

5. 综合与实现(可选,硬件验证)

如果需要在FPGA上验证:

  1. 综合:

    • 在“Flow Navigator”中,点击“Run Synthesis”。
    • 综合完成后,检查“Design Runs”窗口,确保无错误。
  2. 实现:

    • 点击“Run Implementation”。
    • Vivado会生成布局布线结果。
  3. 生成比特流:

    • 点击“Generate Bitstream”。
    • 完成后,找到.bit文件(在项目目录的runs文件夹中)。
  4. 硬件编程:

    • 连接FPGA开发板(例如Nexys 4 DDR)。
    • 在“Flow Navigator”中,点击“Open Hardware Manager”。
    • 选择“Open Target > Auto Connect”连接开发板。
    • 选择“Program Device”,加载生成的.bit文件。
    • 使用外部信号(如开关控制start,LED显示done)验证功能。

6. 保存与归档

  1. 保存项目:
    • 点击 File > Project > Save。
  2. 归档项目(可选):
    • 选择 File > Project > Archive,将项目打包为.zip文件,便于分享或备份。

注意事项

  • 存储器初始化:上述代码在复位时将mem[i]初始化为i(0到31),便于仿真验证。你可以根据需要修改初始化值。
  • 仿真时间:如果交换未完成,增加仿真时间(例如2000ns)。
  • 硬件验证:若在FPGA上测试,需添加约束文件(.xdc)定义clk, rst_n, start, done的引脚。示例约束文件如下(以Nexys 4 DDR为例):
# 时钟(100MHz)
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name sys_clk [get_ports clk]

# 复位(按钮)
set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports rst_n]

# 启动信号(开关)
set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33} [get_ports start]

# 完成信号(LED)
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports done]
  • 错误调试:如果仿真或综合失败,检查“Messages”或“Reports”窗口的错误提示,常见问题包括语法错误或未连接的信号。

预期结果

  • 仿真:存储器内容在start触发后逆序交换,例如mem[0]从00变为1F(31),mem[31]从1F变为00。
  • 硬件:在FPGA上,触发start后,done信号点亮LED,表示交换完成。

原文 https://blog.csdn.net/2301_79518550/article/details/147338291