Vivado Zynq7020 生成正弦波(查表法) + 行为级仿真

======

matlab生成sin函数查表数据

Matlab 复制代码
clear all;clc;
ROM_SIZE = 100;
AMP = 127;
OFFSET = 127;

fprintf('initial begin\n');
for i = 0:ROM_SIZE-1
    value = round(OFFSET + AMP * sin(2*pi*i/ROM_SIZE));
    fprintf('    sine_rom[%d] = 8''d%d;\n', i, value);
end
fprintf('end\n');

======

复制代码
// Encoding: GB2312
// sine_wave.v
/*
实际设计要点与建议
(一)端口声明规则:
牢记输入端口和双向端口只能是 wire 型
输出端口则根据驱动方式决定:若在过程块内赋值,声明为 output reg;若用 assign 驱动,声明为 output wire(或直接省略 wire)
(二)变量选择原则:
先根据设计意图(组合逻辑还是时序逻辑)选择使用 assign 还是 always 块。
再根据赋值位置决定变量类型,在 always 块中操作的变量应声明为 reg,即使最终综合出来的是组合逻辑
(三)避免常见陷阱:
不可在 always 块中对 wire 型变量进行赋值
不可使用 assign 语句对 reg 型变量进行赋值
用于描述时序逻辑的 always 块中,推荐使用非阻塞赋值 (<=) 来避免仿真竞争风险。
(四)理解这些关键字的关键在于跳出"软件编程"思维,时刻思考其对应的硬件电路结构:
wire 是导线,            assign 是连接关系;
reg 是存储单元或中间变量, always 是根据条件触发的行为描述。
只有清晰地区分连续赋值(wire+assign)与过程赋值(reg+always/initial)这两大范式,才能更准确地用 Verilog 来描述所需的硬件功能。
*/

// dout 输出正弦波频率是10Hz,周期是0.1s
module sine_wave (
    input wire clk,
    input wire rst_n,
    output reg [7:0] dout
);

  parameter ROM_SIZE = 100;  // 正弦表长度
  parameter STEP_MAX = 50000;  // 每步计数上限

  reg     [ 7:0] dout1 = 0;
  reg     [15:0] counter = 0;
  reg     [ 6:0] addr = 0;  // ROM地址 0~99

  // 正弦查表,8位幅度 0~255
  reg     [ 7:0] sine_rom                     [0:ROM_SIZE-1];
  integer        i;
  initial begin
    sine_rom[0]  = 8'd127;
    sine_rom[1]  = 8'd135;
    sine_rom[2]  = 8'd143;
    sine_rom[3]  = 8'd151;
    sine_rom[4]  = 8'd159;
    sine_rom[5]  = 8'd166;
    sine_rom[6]  = 8'd174;
    sine_rom[7]  = 8'd181;
    sine_rom[8]  = 8'd188;
    sine_rom[9]  = 8'd195;
    sine_rom[10] = 8'd202;
    sine_rom[11] = 8'd208;
    sine_rom[12] = 8'd214;
    sine_rom[13] = 8'd220;
    sine_rom[14] = 8'd225;
    sine_rom[15] = 8'd230;
    sine_rom[16] = 8'd234;
    sine_rom[17] = 8'd238;
    sine_rom[18] = 8'd242;
    sine_rom[19] = 8'd245;
    sine_rom[20] = 8'd248;
    sine_rom[21] = 8'd250;
    sine_rom[22] = 8'd252;
    sine_rom[23] = 8'd253;
    sine_rom[24] = 8'd254;
    sine_rom[25] = 8'd254;
    sine_rom[26] = 8'd254;
    sine_rom[27] = 8'd253;
    sine_rom[28] = 8'd252;
    sine_rom[29] = 8'd250;
    sine_rom[30] = 8'd248;
    sine_rom[31] = 8'd245;
    sine_rom[32] = 8'd242;
    sine_rom[33] = 8'd238;
    sine_rom[34] = 8'd234;
    sine_rom[35] = 8'd230;
    sine_rom[36] = 8'd225;
    sine_rom[37] = 8'd220;
    sine_rom[38] = 8'd214;
    sine_rom[39] = 8'd208;
    sine_rom[40] = 8'd202;
    sine_rom[41] = 8'd195;
    sine_rom[42] = 8'd188;
    sine_rom[43] = 8'd181;
    sine_rom[44] = 8'd174;
    sine_rom[45] = 8'd166;
    sine_rom[46] = 8'd159;
    sine_rom[47] = 8'd151;
    sine_rom[48] = 8'd143;
    sine_rom[49] = 8'd135;
    sine_rom[50] = 8'd127;
    sine_rom[51] = 8'd119;
    sine_rom[52] = 8'd111;
    sine_rom[53] = 8'd103;
    sine_rom[54] = 8'd95;
    sine_rom[55] = 8'd88;
    sine_rom[56] = 8'd80;
    sine_rom[57] = 8'd73;
    sine_rom[58] = 8'd66;
    sine_rom[59] = 8'd59;
    sine_rom[60] = 8'd52;
    sine_rom[61] = 8'd46;
    sine_rom[62] = 8'd40;
    sine_rom[63] = 8'd34;
    sine_rom[64] = 8'd29;
    sine_rom[65] = 8'd24;
    sine_rom[66] = 8'd20;
    sine_rom[67] = 8'd16;
    sine_rom[68] = 8'd12;
    sine_rom[69] = 8'd9;
    sine_rom[70] = 8'd6;
    sine_rom[71] = 8'd4;
    sine_rom[72] = 8'd2;
    sine_rom[73] = 8'd1;
    sine_rom[74] = 8'd0;
    sine_rom[75] = 8'd0;
    sine_rom[76] = 8'd0;
    sine_rom[77] = 8'd1;
    sine_rom[78] = 8'd2;
    sine_rom[79] = 8'd4;
    sine_rom[80] = 8'd6;
    sine_rom[81] = 8'd9;
    sine_rom[82] = 8'd12;
    sine_rom[83] = 8'd16;
    sine_rom[84] = 8'd20;
    sine_rom[85] = 8'd24;
    sine_rom[86] = 8'd29;
    sine_rom[87] = 8'd34;
    sine_rom[88] = 8'd40;
    sine_rom[89] = 8'd46;
    sine_rom[90] = 8'd52;
    sine_rom[91] = 8'd59;
    sine_rom[92] = 8'd66;
    sine_rom[93] = 8'd73;
    sine_rom[94] = 8'd80;
    sine_rom[95] = 8'd88;
    sine_rom[96] = 8'd95;
    sine_rom[97] = 8'd103;
    sine_rom[98] = 8'd111;
    sine_rom[99] = 8'd119;
  end

  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      counter <= 0;
      addr <= 0;
      dout <= 127;
    end else begin
      if (counter < STEP_MAX - 1) begin
        counter <= counter + 1;
      end else begin
        counter <= 0;
        if (addr < ROM_SIZE - 1) addr <= addr + 1;
        else addr <= 0;
        dout <= sine_rom[addr];
      end
    end
  end
endmodule

======

复制代码
// Encoding: GB2312
// sine_wave_tb.v
`timescale 1ns/1ps //时间单位1ns/时间精度1ps
module tb_sine_wave;
    parameter SIM_TIME_MS = 500;    // 定义仿真时间,单位毫秒(正弦波频率是10Hz,周期是0.1s,显示5个周期用时0.5s=500ms)
    parameter CLK_PERIOD_NS = 20;   // 定义时钟周期,单位纳秒

    reg clk = 0;
    reg rst_n = 0;
    wire [7:0] dout;

    sine_wave uut (
        .clk(clk),
        .rst_n(rst_n),
        .dout(dout)
    );

    // 使用参数生成时钟
    always #(CLK_PERIOD_NS/2) clk = ~clk;

    initial begin
        $display("SIM START");
        #100;
        rst_n = 1;
        // 使用参数控制仿真时间 (转换为ns)
        #(SIM_TIME_MS * 1_000_000);     //仿真时间到达500ms,仿真自动停止
        $display("SIM END");
        $stop;                          //仿真时间到达500ms,仿真自动停止
    end
endmodule

======

======

======

相关推荐
Terasic友晶科技3 小时前
4-DE10-Nano的HDMI方块移动案例——I2C通信协议
fpga开发·i2c·hdmi·de10-nano·i2c通信协议
云雾J视界15 小时前
FPGA在AI时代的角色重塑:硬件可重构性与异构计算的完美结合
fpga开发·边缘计算·gpu·vitis·ai推理·azure云·异构编程
s09071361 天前
FPGA中CIC设计注意事项
算法·fpga开发·cic滤波器
Aaron15881 天前
RFSOC+VU13P在无线信道模拟中的技术应用分析
数据结构·人工智能·算法·fpga开发·硬件架构·硬件工程·射频工程
碎碎思2 天前
BerkeleyLab Bedrock:为 FPGA 与加速计算打造的开源基石
fpga开发·开源
zidan14122 天前
xilinx常用文档说明
fpga开发
ShiMetaPi2 天前
GM-3568JHF丨ARM+FPGA异构开发板系列教程:外设教程 04 WIFI
网络·arm开发·fpga开发·智能路由器·fpga
FPGA_小田老师2 天前
FPGA基础知识(二十):Xilinx Block Memory IP核(5)--ROM 详解
fpga开发·rom·coe文件格式·导入coe·block memory
FPGA_无线通信2 天前
压缩解压缩算法 BFP-8bit
fpga开发