赞
踩
总共分为四个模块:
1.数据源采集模块:
1.ad数据采集模块:tl549_interface(本模块主要从TL549中读取信号采样的数据)
该模块使用adTL549协议进行ad数据传输,其中所需的接口:ad部分接口:cs,sdi,scl、人机控制采样信号:ad_en、
采样传输到下一个模块的数据信号和数据有效信号:ad_data,flag_ad_data。
(其中需要注意代码写法:序列机的0状态空闲,计数器可以用输入的人机交互信号进行控制,71+(25*0 )上升沿scl置1,数据由高位先输入,
数据有效位在最后一个数据生成时非阻塞生成一个时钟周期的信号)
2.dds数据采集模块:dds(本模块完成频率可调,相位可调的dds)
** module dds
**(
** //模块工作相关信号
** input clk_50mhz,//默认DDS原始参考采样时钟为50mhz
** input rst_n,//系统复位
**
**
** //与dds信号相关信号
** output [7:0] dds_data,//输出PCM编码,默认8位
** output flag_dds_data,
**
**
** //人机交互相关信号
** input [31:0]fword,//调频因子
** input [10:0]pword, //相位地址偏移
** input dds_en
**);
**
**//调频程序实现,精度N=32,原始信号一个周期采样点数为2^32
**reg [31:0] rom_addr_vir;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** rom_addr_vir[31:0] <= 32'd0;
** else
** rom_addr_vir[31:0] <= rom_addr_vir[31:0] + fword[31:0];
**//由于FPGA内部的存储资源有限,不能够存放N=32的采样的所有采样数据,因此我们从2^32个点钟等间隔抽取2048个点
**reg [10:0] rom_addr;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** rom_addr <= 11'd0;
** else
** rom_addr <= rom_addr_vir[31:21] + pword[10:0];
**
**assign flag_dds_data = dds_en;
**
**
**rom rom_inst (
** .address ( rom_addr ),
** .clock ( clk_50mhz ),
** .q ( dds_data )
** );
**
**endmodule
1.在判断时,频率和相位的加减在RTL写法下是相同的(都是相加)频率对应的数据位宽[31:0],相位对应的位宽[10:0]
2.数据有效位输出 assign flag_dds_data = dds_en;(rom中的地址一直在加,当有效信号来临时,数据输出再进行地址循环相加,数据循环输出,dds产生波形,相当于产生的波形起始位时随机的,就当有效信号来临时数据输出,有效信号结束,产生波形截止)
2.数据通道选择模块:
1.独立按键消抖模块:key_dec(本模块主要对独立按键消抖)
两种方式:第一种状态机计数,计10ms停止(相当于从1-0中间间隔10ms,0持续10ms)
第二种用计数,三个寄存器相与打拍操作(简洁)(相当于从1-0中间间隔36ms,0持续到检测按键置1状态,置1)
//本模块主要对独立按键消抖
**module key_dec
**(
** //模块工作相关信号
** input clk_50mhz,
** input rst_n,
**
** //与独立按键相关信号
** input key,//原始按键检测电平输入
** output flag_key//消除抖动后的电平输出
**
**);
**//本程序通过每次间隔默认12ms对原始按键检测电平进行采样,连续采样3次
**reg sap_en;//定义采样使能,使能之间间隔12ms
**reg [19:0]cnt;
**always @(posedge clk_50mhz or negedge rst_n )
** if(~rst_n)begin
** cnt <=20'd0;
** sap_en <= 1'b0;end
** else if(cnt == (20'd600000-1'b1))begin
** cnt <=20'd0;
** sap_en <= 1'b1;end
** else begin
** cnt <= cnt +1'b1;
** sap_en <= 1'b0;end
**
**reg key1,kye2,key3;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)begin
** key1 <= 1'b1;
** kye2 <= 1'b1;
** key3 <=1'b1;end
** else if(sap_en)begin
** key1 <= key;
** kye2 <= key1;
** key3 <= kye2;
** end
**assign flag_key = ~( (~key1) & (~kye2) & (~key3) ) ;
**endmodule
2.按键通道选择模块:ch_sel(按键信号边沿检测,选择通道)
首先进行边沿检测,再进行通道0.1选择,取反操作,数据=输入ad数据or输入dds数据。
3.命令参数解析控制模块:
通过uart接收解析包中(解析包中需要控制定义相关寄存器的地址标号,使用uart进行串口调试时,需要进行输入)需要控制输入数据的数据信号,
将数据通过解析产生总线(使能,数据,数据有效),通过总线产生控制uart时钟,通过总线产生控制调频调相的数据
1.uart接收数据模块:uart_receive(本模块通过uart接收数据)
****通过使能信号clk_r控制传输速率,不用自己写15倍时钟。(相当于在所需要使用变化时钟模块的所有always下,先使用此信号进行判断条件)
**//奇偶校验模块
**always @(posedge clk_50mhz or negedge rst_n )
** if(~rst_n)
** flag_rvdata <=1'b0;
**** else if(clk_r && (cnt==(14+(15*8) +7) )) begin
** //odd(奇校验) eve(偶校验) mark(填充1) space(填充0)
** (奇偶校验位判断时,首先在数据传输之前确定奇校验还是偶校验,若此模块开始为偶校验1,此时判断数据中1的个数,若为偶数,则对应偶校验,条件则成立输出)(偶校验数据中1的个数为偶数,校验位为1,奇校验反之)
** if( rvdata[0]^rvdata[1]^rvdata[2]^rvdata[3]^rvdata[4]^rvdata[5]^rvdata[6]^rvdata[7]^ rx )
** flag_rvdata <=1'b1;
** else
** flag_rvdata <=1'b0;end
** else
** flag_rvdata <=1'b0;
2.将数据包的内容进行解析,将数据传输到数据总线:pk_conv(本模块将软件发送的包数据进行解析,然后通过系统总线数据转发)
****wr_en使能信号:相当于在一个包数据接收完成时,使能信号拉高,此时数据线和数据有效线的值为当前包的数据值,
直接运用到需要使能信号进行控制,数据直接赋值的条件下。(一个使能对应一个16位数据,如果该数据32位,则定义中间寄存器暂存)
**//wr_en总线使能信号生成
**always @(posedge clk_50mhz or negedge rst_n )
** if(~rst_n)
** bus_wr <=1'b0;
** else if( (state == PK_TAIL) && (rvdata == 8'h66 ) && flag_rvdata )//检查完是否接收一个完整的包
** bus_wr <=1'b1;
** else
** bus_wr <=1'b0;
3.通过寄存器配置,控制uart接收或者发送解析包中控制用数据:uart_band_ctl(本模块主要是通过寄存器配置,控制uart接收或者发送是速率)
**//本模块主要是通过寄存器配置,控制uart接收或者发送是速率
**module uart_band_ctl
**(
** //模块工作相关信号
** input clk_50mhz,
** input rst_n,
**
** //接收寄存器配置信号相关信号
** input bus_wr,
** input [7:0] bus_addr,
** input [15:0] bus_data,
**
**
** //与uart速率控制相关信号
** output reg clk_r,//本地控制uart接收
** output reg clk_t //本地控制uart发送
**);
**reg [2:0]uart_band_sel;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** uart_band_sel <= 3'd0;
** else if(bus_wr && (bus_addr[7:0]==3'd7))
** uart_band_sel <= bus_data[2:0];
**
**parameter FSYS_CLK = 26'd50_000_000 ;
**parameter BAND_1152000 = (FSYS_CLK/26'd115200 ) ,
** BAND_57600 = (FSYS_CLK/26'd57600 ) ,
** BAND_56000 = (FSYS_CLK/26'd56000 ) ,
** BAND_38400 = (FSYS_CLK/26'd38400 ) ,
** BAND_28800 = (FSYS_CLK/26'd28800 ) ,
** BAND_19200 = (FSYS_CLK/26'd19200 ) ,
** BAND_14400 = (FSYS_CLK/26'd14400 ) ,
** BAND_9600 = (FSYS_CLK/26'd9600 ) ;
**
**//uart发送默认采用速率等效的时钟信号控制发送
**reg [11:0]cnt_t,cnt_t_max;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)begin
** clk_t <= 1'b0;
** cnt_t <= 12'd0;end
** else if(cnt_t == cnt_t_max )begin
** clk_t <= ~clk_t;
** cnt_t <= 12'd0;end
** else
** cnt_t <= cnt_t + 1'b1;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** cnt_t_max <= 12'd0;
** else case(uart_band_sel[2:0])
** 0 :cnt_t_max <= ((BAND_1152000/2'd2)-1'b1);
** 1 :cnt_t_max <= ((BAND_57600/2'd2)-1'b1);
** 2 :cnt_t_max <= ((BAND_56000/2'd2)-1'b1);
** 3 :cnt_t_max <= ((BAND_38400/2'd2)-1'b1);
** 4 :cnt_t_max <= ((BAND_28800/2'd2)-1'b1);
** 5 :cnt_t_max <= ((BAND_19200/2'd2)-1'b1);
** 6 :cnt_t_max <= ((BAND_14400/2'd2)-1'b1);
** 7 :cnt_t_max <= ((BAND_9600/2'd2)-1'b1);
** default:cnt_t_max <= cnt_t_max;
** endcase
**
**//接收默认采样速率等效时钟的15倍使能信号作为控制接收
**reg [8:0] cnt_r,cnt_r_max;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)begin
** clk_r <=1'b0;
** cnt_r <=9'd0;end
** else if(cnt_r == cnt_r_max)begin
** clk_r <= 1'b1;
** cnt_r <=9'd0;end
** else begin
** clk_r <=1'b0;
** cnt_r <= cnt_r +1'b1;end
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** cnt_r_max <= 9'd0;
** else case(uart_band_sel[2:0])
** 0:cnt_r_max <= ((BAND_1152000/4'd15)-1'b1);
** 1:cnt_r_max <= ((BAND_57600/4'd15)-1'b1);
** 2:cnt_r_max <= ((BAND_56000/4'd15)-1'b1);
** 3:cnt_r_max <= ((BAND_38400/4'd15)-1'b1);
** 4:cnt_r_max <= ((BAND_28800/4'd15)-1'b1);
** 5:cnt_r_max <= ((BAND_19200/4'd15)-1'b1);
** 6:cnt_r_max <= ((BAND_14400/4'd15)-1'b1);
** 7:cnt_r_max <= ((BAND_9600/4'd15)-1'b1);
** default:cnt_r_max <= cnt_r_max;
** endcase
**endmodule
4.通过数据采集系统进行数据采集:data_sap_ctl(本模块通过寄存器控制数据采集系统数据采集控制)
****为了逻辑严谨:在控制fword时,需要将数据低[7:0]存入中间变量,再和高[15:8]数据结合起来。
调频,调相初始值不能为0或者小数,复位置1。
ad和dds采样率控制时,定义计数器和采样数据最大值,最大值由总线数据输出,比较计数器计数值=采样数据最大值,输出使能信号
**//本模块通过寄存器控制数据采集系统数据采集控制
**module data_sap_ctl
**(
** //模块工作相关信号
** input clk_50mhz,
** input rst_n,
**
** //寄存器参数接收相关信号
** input bus_wr,
** input [7:0] bus_addr,
** input [15:0] bus_data,
**
** //与信号采集相关的控制信号
** output reg[31:0]fword,//控制DDS调频
** output reg[10:0]pword,//控制DDS调相
** output ad_en,//控制TL549采样率
** output dds_en//控制DDS采样率
**);
**//DDS调频控制
**reg [15:0]fword_l16;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)begin
** fword_l16 <= 16'd0;
** fword <= 31'd1000;end
** else if(bus_wr )
** case(bus_addr[7:0] )
** 0:fword_l16[15:00] <= bus_data[15:0];
** 1:fword[31:00] <= {bus_data[15:0],fword_l16[15:0]};
** default:fword<= fword;
** endcase
**//DDS调相
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** pword <= 11'd0;
** else if(bus_wr && bus_addr[7:0]==8'd2)
** pword <=bus_data[10:0] ;
**
**//ad采样率控制
**reg [31:0]cnt_ad_sap, ad_sap_max;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** cnt_ad_sap <= 32'd0;
** else if(cnt_ad_sap == ad_sap_max )
** cnt_ad_sap <= 32'd0;
** else
** cnt_ad_sap <= cnt_ad_sap +1'b1;
**assign ad_en = (cnt_ad_sap == ad_sap_max )?1'b1:1'b0;
**
**
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** ad_sap_max <= 32'd5300;
** else if(bus_wr )
** case(bus_addr[7:0])
** 3:ad_sap_max[15:00] <= bus_data[15:0];
** 4:ad_sap_max[31:16] <= bus_data[15:0];
** default:ad_sap_max <= ad_sap_max;
** endcase
**
**//DDS采样率控制
**reg [31:0]cnt_dds_sap,dds_sap_max;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** cnt_dds_sap <= 32'd0;
** else if(cnt_dds_sap == dds_sap_max )
** cnt_dds_sap <= 32'd0;
** else
** cnt_dds_sap <= cnt_dds_sap+1'b1;
**assign dds_en = (cnt_dds_sap == dds_sap_max )?1'b1:1'b0;
**always @(posedge clk_50mhz or negedge rst_n)
** if(~rst_n)
** dds_sap_max <= 32'd5300;
** else if(bus_wr)
** case(bus_addr[7:0])
** 5:dds_sap_max[15:00]<= bus_data[15:0];
** 6:dds_sap_max[31:16]<= bus_data[15:0];
** default:dds_sap_max <= dds_sap_max;
** endcase
**endmodule
4.采集数据传输:
1.读取fifo数据,通过uart发送:uart_trans(本模块主要读取FIFO的数据,通过uart发送)
**//读使能在fifo不空和计数条件下开始读数据
**reg [3:0]cnt;
**always @(posedge Clk_t or negedge rst_n)
** if(~rst_n)
** cnt <= 4'd0;
** else case(cnt)
** 4'd00: if(~empty)cnt <= cnt+1'b1;
** 4'd11: cnt <= 4'd0;
** default:cnt <= cnt+1'b1;
** endcase
**//Fifo读数据程序
**assign rd_clk = Clk_t;
**assign rd_en = ((cnt==4'd0) && (~empty) )?1'b1:1'b0;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。