ROM介绍
ROM 代表只读存储器(Read-Only Memory),是一种电子存储设备,用于存储计算机系统启动程序、固件、操作系统和其他重要数据,比如说电脑中使用的磁盘。与随机存储器(RAM)不同, ROM 存储的数据一旦写入后断电后不会丢失, RAM断电后数据直接丢失, 因此 ROM 也被称为非易失性存储器(Non-Volatile Memory)。
FPGA中是有一定的存储资源,常见就是BRAM,本实验通过调用FPGA的IP核, IP 核相当于是已经写好的模块, 来实现 ROM 的功能,不过这个 ROM 本质是 RAM,断电后数据会丢失,只是具有 ROM 的功能。
单口ROM配置
首先在IP Catalog中找到Block Memory Generator并打开
端口设置
coe文件初始化ROM(coe文件可以由matlab生成,也可由软件生成)
此处coe文件存的是正弦波形数据
检查无误点击OK生成ip核
代码示例
ROM模块例化
//正弦波
sin_wave_rom sin_wave_rom_inst
(
.clka(clk),
.addra(addr),
.douta(dac_data0)
);
控制addr信号来实现对ROM数据的读取
//相位累加器
reg [31:0] fre_acc;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
fre_acc <= 0;
end
else begin
fre_acc <= fre_acc + f_word;
end
end
//生成查找表地址
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
addr <= 0;
end
else begin
addr <= fre_acc[31:20] + p_word;
end
end
dds模块
`timescale 1ns / 1ps
module dds(
input clk ,
input rst_n ,
input [31:0] f_word , //频率设置
input [1:0] wave_c , //波形选择
input [13:0] p_word , //相位偏移量--------------->控制相位---------pi/2对应1024
//input [4:0] amplitude , //幅值控制
output reg [13:0] dac_data
);
wire [4:0] amplitude;
assign amplitude = 1'b1;
localparam DATA_WIDTH = 4'd14; //DAC数据位宽
localparam ADDR_WIDTH = 4'd12; //ROM地址位宽
reg [ADDR_WIDTH - 1 :0] addr ;
wire [DATA_WIDTH - 1 :0] dac_data0;
wire [DATA_WIDTH - 1 :0] dac_data1;
wire [DATA_WIDTH - 1 :0] dac_data2;
wire [DATA_WIDTH - 1 :0] dac_data3;
//波形选择
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
dac_data <= 14'd0;
end
else begin
case(wave_c)
2'b00:dac_data <= dac_data0/amplitude; //正弦波
2'b01:dac_data <= dac_data1/amplitude; //三角波
2'b10:dac_data <= dac_data2/amplitude; //锯齿波
2'b11:dac_data <= dac_data3/amplitude; //方波
default:;
endcase
end
end
//相位累加器
reg [31:0] fre_acc;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
fre_acc <= 0;
end
else begin
fre_acc <= fre_acc + f_word;
end
end
//生成查找表地址
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
addr <= 0;
end
else begin
addr <= fre_acc[31:20] + p_word;
end
end
//正弦波
sin_wave_rom sin_wave_rom_inst
(
.clka(clk),
.addra(addr),
.douta(dac_data0)
);
//三角波
tri_wave_rom tri_wave_rom_inst
(
.clka(clk),
.addra(addr),
.douta(dac_data1)
);
//锯齿波
saw_wave_rom saw_wave_rom_inst
(
.clka(clk),
.addra(addr),
.douta(dac_data2)
);
//方波
squ_wave_rom squ_wave_rom_inst
(
.clka(clk),
.addra(addr),
.douta(dac_data3)
);
// ila_0 ila_0_inst
// (
// .clk(clk),
// .probe0(addr),
// .probe1(dac_data)
// );
endmodule
生成8x1024的正弦波波形coe文件的matlab程序
X=linspace(0,2*pi,1024);%在0-2π之等间距生成1024个点
Y=(255/2)*(sin(X)+1);%0-255之间的正弦信号
Y=uint8(Y); %把值转化为8位的无符号数
plot(X,Y); %画出图像
fid0 = fopen('sin8x1024.coe', 'wt');%打开一个文件
fprintf(fid0,'MEMORY_INITIALIZATION_RADIX=16;\nMEMORY_INITIALIZATION_VECTOR=\n');%先写入coe文件都需要加的一句话
fprintf(fid0, '%02x,\n', Y);%将矩阵按照2位16进制数输出,填充0占位
fid0 = fclose(fid0);%关闭这个文件