FPGA数字系统设计(9)——信号产生

信号的数字化需要3个步骤:抽样、量化和编码。抽样是指用每隔一定时间的信号样值序列来代替原来在时间上的连续信号,也就是在时间上将模拟信号离散化。量化使用有限个幅度值来近似原来连续变化的幅度值,把模拟信号的连续幅度变为有限数量的且有一定间隔的离散值。编码则是按照一定的规律,把量化后的值用二进制数表示,然后转换成二值或者多值的数字信号流。上述的数字化过程又称为脉冲编码调制。
这里讨论两种FPGA实现信号发生器的方法
一、利用FPGA上集成的IP核RAM核或ROM核实现正弦波信号的产生。
1、使用MATLAB实现mif文件的编写或者直接使用Mif_Maker2010生成mif文件:
首先是MATLAB实现信号的产生以及mif文件的生成

clc,clear;
N=2^8;  %N为采样点数
s_p=0:255;%正弦波一个周期的采样点数
sin_data=sin(2*pi*s_p/N);  %sin_data是初步采样值,浮点数% 编写到这里,大家可以在任务行中显示此时的波形
fix_p_sin_data=fix(sin_data*127); %定点化 fix()函数可以直接去除小数点后的值,使之成为整数
for i=1:N 
    fix_p_sin_data(i) = N/2+fix_p_sin_data(i)
end%下面是mif文件固定格式,不可更改
fid=fopen('E:\FPGA\1_Verilog\sin\sp_ram_256x8.mif','w+');
fprintf(fid,'WIDTH=8;\n');
fprintf(fid,'DEPTH=256;\n');
fprintf(fid,'ADDRESS_RADIX=UNS;\n');
fprintf(fid,'DATA_RADIX=UNS;\n');
fprintf(fid,'CONTENT BEGIN \n');
for i=1:N
fprintf(fid,'%d:%d; \n',i-1,fix_p_sin_data(i));
end
fprintf(fid,'END; \n');
fclose(fid);

以上MATLAB代码实现一个正弦波的一个周期同时将这个正弦信号生成mif文件。生成的mif的文件是一个宽为8,深度为256,这个在后续的RAM核和ROM核的设计中使用的到。生成的mif文件用Quertus II 核文本两种形式查看如下图所示
在这里插入图片描述
在这里插入图片描述
这里需要注意的是产生的mif文件只能是无符号整数,因为是数字信号发生器,只能实现整数的信号处理。
接下来是使用Mif_Maker2010生成mif文件,该文件我会放在文本后。在这里插入图片描述
通过全局参数设置实现波形的生成。然后另存为mif文件就可生成一个包含波形的mif文件。
2、RAM核与ROM核的生成
首先建立一个sin工程,然后开始IP核的建立

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述这是选择视紫红核存储器的类型,以及ram或rom的宽度核深度,这里要和之前的mif文件对应在这里插入图片描述
在这里插入图片描述
这里选之前生成的mif文件作为存储器里包含的数据。需要注意的是最好将生成的mif文件放在工程目录下,否则会对后续的仿真产生很大的影响。(血的教训,整整花费了我8个小时才找到的原因。后续会讲)
在这里插入图片描述
在这里插入图片描述
之前没讲的都直接next,最后finish,完成了一个宽为地址和数据位均为8位的rom核的生成,RAM核生成的过程与此过程一致,这里就不再赘述。
3、接下来我们主要看以下两个文件
在这里插入图片描述

首先是inst文件
rom1port rom1port_inst (
 .address ( address_sig ),
 .clock ( clock_sig ),
 .q ( q_sig )
 );
这是一个例化过程的模板,直接拷贝,修改接口即可完成对rom核的例化。

接下来是rom1port.v文件
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module rom1port (
 address,
 clock,
 q);
 input [7:0]  address;
 input   clock;
 output [7:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
 tri1   clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [7:0] sub_wire0;
 wire [7:0] q = sub_wire0[7:0];
altsyncram altsyncram_component (
    .address_a (address),
    .clock0 (clock),
    .q_a (sub_wire0),
    .aclr0 (1'b0),
    .aclr1 (1'b0),
    .address_b (1'b1),
    .addressstall_a (1'b0),
    .addressstall_b (1'b0),
    .byteena_a (1'b1),
    .byteena_b (1'b1),
    .clock1 (1'b1),
    .clocken0 (1'b1),
    .clocken1 (1'b1),
    .clocken2 (1'b1),
    .clocken3 (1'b1),
    .data_a ({
    
    8{
    
    1'b1}}),
    .data_b (1'b1),
    .eccstatus (),
    .q_b (),
    .rden_a (1'b1),
    .rden_b (1'b1),
    .wren_a (1'b0),
    .wren_b (1'b0));
 defparam
  altsyncram_component.address_aclr_a = "NONE",
  altsyncram_component.clock_enable_input_a = "BYPASS",
  altsyncram_component.clock_enable_output_a = "BYPASS",
  altsyncram_component.init_file = "sp_ram_256x8.mif",
  altsyncram_component.intended_device_family = "Cyclone IV E",
  altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
  altsyncram_component.lpm_type = "altsyncram",
  altsyncram_component.numwords_a = 256,
  altsyncram_component.operation_mode = "ROM",
  altsyncram_component.outdata_aclr_a = "NONE",
  altsyncram_component.outdata_reg_a = "CLOCK0",
  altsyncram_component.widthad_a = 8,
  altsyncram_component.width_a = 8,
  altsyncram_component.width_byteena_a = 1;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
// Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: Clken NUMERIC "0"
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
// Retrieval info: PRIVATE: MIFfilename STRING "../../sp_ram_256x8.mif"
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "256"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
// Retrieval info: PRIVATE: RegOutput NUMERIC "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
// Retrieval info: PRIVATE: WidthAddr NUMERIC "8"
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
// Retrieval info: PRIVATE: rden NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: INIT_FILE STRING "../../sp_ram_256x8.mif"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL "address[7..0]"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
// Retrieval info: CONNECT: @address_a 0 0 8 0 address 0 0 8 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port.inc TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port.cmp TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port.bsf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port_inst.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL rom1port_bb.v TRUE
// Retrieval info: LIB_FILE: altera_mf
通过查看信息,可以看到rom核设置的一些信息,我那个仿真不出结果就是在这里的mif文件位置查到不在工程文件夹下,才找到的原因。

3、顶层文件设计

/* time:  2020.9.1
 主要功能:实现正弦信号的产生,可以通过对信号的地址加的数字修改输出信号的频率
 端口定义: clock:时钟信号
        reset:复位信号
    o_wave:输出信号
==================================================================*/
module sin(clock, reset, o_wave);
input clock, reset;
output [7:0] o_wave;
reg [7:0] addr;
wire [7:0] o_wave;
always @(posedge clock or negedge reset)begin
 if(!reset)
 begin
  addr <= 8'b0;
 end 
 else
 begin
  addr <= addr + 8'd2;            //修改这里可以修改输出的频率
 end 
end 
rom1port rom1port_inst (
 .address ( addr ),
 .clock ( clock ),
 .q ( o_wave )
 );
endmodule

RTL电路如下图所示
在这里插入图片描述
仿真电路如下图所示:
这里说一下最好使用联合仿真,因为手动仿真会有问题,会输出高阻态。手动仿真可以参考我的转载的另一篇文档:
在这里插入图片描述二、NCO(Numerically Controlled Oscillator)数控振荡器

利用IP核进行设置,自动生成然后顶层文件对IP核进行例化即可。
声明:该文只适用于学习,其内容包含来自书本的摘抄和总结,欢迎s大家补充,共同学习进步。

猜你喜欢

转载自blog.csdn.net/qq_24213087/article/details/108089314
今日推荐