======
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
======

======

======