文章目录

  • 前言
  • 一、调制解调概念
    • 1.2FSK原理
  • 二、硬件设计
    • 1.调制器设计思路
    • 2.解调器设计思路
  • 三、代码
    • 1.顶层
    • 2.F1载波发生模块
    • 3.F2载波发生模块
    • 4.频率计模块
    • 5.测试文件
  • 四、仿真结果

前言

  在某些具体情况下,如通过电话线传输信息时,由于在电话线上只能传输模拟信号,因此需要将数字信号转换为模拟信号,进而将转换后的模拟信号进行传输。数据接收端对模拟信号进行采样,量化,编码后,还原出数字信号。
  在上述过程中,数据发送端将数字信号转换为模拟信号的过程叫做调制,数据接收端将模拟信号转为数字信号的过程叫做解调。

一、调制解调概念

  数字信号调制的方法有很多,根据不同原理,有2FSK(二进制频率调制)、2PSK(二进制相移键控)、2ASK(二进制振幅键控)等等。但不管哪种方法,都建立了一种二进制信息与模拟信息之间的关系,当然不同的调制方法其对频带的利用率也有所不同。
  本篇主要进行基于2FSK的二进制信号调制的实验。

1.2FSK原理

  2FSK是通过所要传输的数字信息控制载波的频率。如图1.0所示,现有两种不同频率的载波f1与f2,在数据发送端对输入信号进行调制时,根据当前所需要发送的数据Din,选择不同的载波,可以定义为 当 din=0b时,dout端口输出载波f1,当din=1b时,dout端口输出载波f2,则在dout端口输出的波形可以如图1.1中所示
               图1.0 2FSK硬件原理简图

               图1.1 2FSK波形图

  上述为调制部分,解调部分其实就是调制部分的逆过程,通过接收模拟信号,然后转换为数字量,进而计算信号的频率,然后对应还原基带信号。

二、硬件设计

1.调制器设计思路

  根据其原理,在设计调制器时,需要一个产生载波的模块,该模块需要能够产生两个不同频率的sin波形;其次需要一个移位寄存器作为数据的发送缓冲区;其大致结构如图2.0所示。

               图2.0 2FSK调制器结构
  这里需要注意的是,为了保证每个传输数据都能有一个完整周期的载波表示,移位寄存器的时钟分频应当是载波f1与f2分频的整数倍乘积。

2.解调器设计思路

  解调器实际上是一个频率计,频率计实时计算输入信号的频率,在通过一个频率的阈值比较器,判断输出的数字信号为1或0。
  这里由于考虑到模拟信号在传输过程中可能引入的干扰信号,为了不使通信出错,所以在频率计输入前再增加一个施密特触发器。其结构如图2.1所示。

               图2.1 2FSK解调器结构
  施密特触发器将输入模拟信号转换为边沿脉冲信号,然后通过频率计计算频率,最终转换为数字信号输出。

三、代码

1.顶层

module        FSK_2#(parameter integer CLOCK_DIV = 80
)(input                fsk_clk,input                de_fsk_clk,//解调时钟input                fsk_en,input                fsk_rst,input      [7:0]         din,input      [7:0]       dqvld,//数据有效信号output                    do,output                   deo,output     [7:0]        dout,output     [15:0]      fre_o,output reg         send_qvld,//发送完成信号output reg             sbusy //繁忙标志位);localparam IDLE0 = 4'd0;localparam IDLE1 = 4'd1;localparam SEND = 4'd2;localparam FINISH = 4'd3;wire [7:0] f1_out;wire [7:0] f2_out;reg  [7:0] send_buff;//发送数据缓冲区reg [15:0] div_cnt;wire        send_clk;//数据发送时钟assign send_clk = div_cnt < ((CLOCK_DIV>>1)-1) ? 1'b1:1'b0;//分频always@(posedge fsk_clk,posedge fsk_rst)beginif(fsk_rst)begindiv_cnt <= 16'd0;endelsebeginif(fsk_en)beginif(div_cnt != CLOCK_DIV-1)div_cnt <= div_cnt + 16'd1;elsediv_cnt <= 16'd0;endelsebegin  div_cnt <= div_cnt;endendend//数据发送状态机reg  [3:0] send_state;//发送数据缓冲区reg [3:0] bit_cnt;assign do = send_buff[0];assign dout = do ? f1_out:f2_out;always @ (posedge send_clk,posedge fsk_rst)beginif(fsk_rst)beginsend_buff <= 8'd0;send_state <= 8'd0;send_qvld <= 1'b0;sbusy <= 1'b0;bit_cnt <= 4'd0;endelsebeginif(fsk_en)begincase(send_state)IDLE0:begin//空闲sbusy <= 1'b0;bit_cnt <= 4'd0;if(dqvld)beginsend_buff <= din;send_state <= IDLE1;endelsebeginsend_state <= IDLE0;endendIDLE1:begin//等待qvld撤销sbusy <= 1'b1;if(dqvld)beginsend_state <= IDLE1;endelsebeginsend_state <= SEND;endendSEND:beginif(bit_cnt != 4'd8)begin    send_buff <= send_buff >> 1;bit_cnt <= bit_cnt + 4'd1;endelsebegin send_state <= FINISH; endendFINISH:beginsend_qvld <= 1'b1;send_state <= IDLE0;endendcaseendelsebegin send_buff<=send_buff;send_state<=send_state; bit_cnt <= bit_cnt;send_qvld <= 1'b0;  endendendF1 F1_inist0(.  f1_clk(fsk_clk),.   f1_en(fsk_en),.  f1_rst(fsk_rst),.    dout(f1_out));F2 F2_inist0(.  f2_clk(fsk_clk),.   f2_en(fsk_en),.  f2_rst(fsk_rst),.    dout(f2_out));assign deo = fre_o >= 34? 1'b1:1'b0;cymo #(.SCH_thread0(130))cymo_inist0(. cy_clk(de_fsk_clk),.    din(dout),.  cy_en(fsk_en),. cy_rst(fsk_rst),.  fre_o(fre_o));endmodule

  在顶层模块中除了例化了f1与f2两个载波的发生模块和频率计模块外,还通过两个always块实现了移位寄存器和FSK的状态控制。
  在信号接口中,do为调制器需要调制的基带信号,deo为最终的解调信号。

2.F1载波发生模块

//10点采样sin波形
module F1(input             f1_clk,input              f1_en,input             f1_rst,output reg [7:0]    dout);parameter integer sin0 = 128;parameter integer sin1 = 203;parameter integer sin2 = 250;parameter integer sin3 = 250;parameter integer sin4 = 203;parameter integer sin5 = 128;parameter integer sin6 = 52;parameter integer sin7 = 6;parameter integer sin8 = 6;parameter integer sin9 = 52;reg [3:0] f1_state;always @ (posedge f1_clk,posedge f1_rst)beginif(f1_rst)beginf1_state <= 4'd0;endelsebeginif(f1_en)beginif(f1_state != 4'd9)beginf1_state <= f1_state+4'd1;endelsebegin  f1_state <= 4'd0; endendelsebeginf1_state <= f1_state;endendendalways @ (posedge f1_clk,posedge f1_rst)beginif(f1_rst)beginf1_state <= 4'd0;dout <= sin0;endelsebeginif(f1_en)begincase(f1_state)4'd0:begin dout <= sin0; end    4'd1:begin dout <= sin1; end  4'd2:begin dout <= sin2; end4'd3:begin dout <= sin3; end4'd4:begin dout <= sin4; end    4'd5:begin dout <= sin5; end 4'd6:begin dout <= sin6; end4'd7:begin dout <= sin7; end4'd8:begin dout <= sin8; end4'd9:begin dout <= sin9; enddefault:begin dout<=sin0; endendcaseendelsebegin dout<=dout; endendend    endmodule

  载波可以通过cordic IP核计算发出,这里为了方便,选择了查表法。f1载波是10点采样的sin波形。

3.F2载波发生模块

//8点采样sin波形
module F2(input             f2_clk,input              f2_en,input             f2_rst,output reg [7:0]    dout);parameter integer sin0 = 128;parameter integer sin1 = 218;parameter integer sin2 = 255;parameter integer sin3 = 218;parameter integer sin4 = 128;parameter integer sin5 = 37;parameter integer sin6 = 0;parameter integer sin7 = 37;reg [3:0] f2_state;always @ (posedge f2_clk,posedge f2_rst)beginif(f2_rst)beginf2_state <= 4'd0;endelsebeginif(f2_en)beginif(f2_state != 4'd7)beginf2_state <= f2_state+4'd1;endelsebegin  f2_state <= 4'd0; endendelsebeginf2_state <= f2_state;endendendalways @ (posedge f2_clk,posedge f2_rst)beginif(f2_rst)beginf2_state <= 4'd0;dout <= sin0;endelsebeginif(f2_en)begincase(f2_state)4'd0:begin dout <= sin0; end    4'd1:begin dout <= sin1; end  4'd2:begin dout <= sin2; end4'd3:begin dout <= sin3; end4'd4:begin dout <= sin4; end    4'd5:begin dout <= sin5; end 4'd6:begin dout <= sin6; end4'd7:begin dout <= sin7; enddefault:begin dout<=sin0; endendcaseendelsebegin dout<=dout; endendend    endmodule

  f2同样采用查表法,是8点采样的sin波形。
  假设现在f1与f2模块的输入时钟为10Mhz,则不难得出,f1频率为10Mhz/10 = 1Mhz ,f2频率为 10Mhz/8 = 1.125Mhz。

4.频率计模块

module cymo#(parameter integer SCH_thread0 = 150
)(input            cy_clk,input         [7:0] din,input             cy_en,input             cy_rst,output reg [15:0]  fre_o);localparam  SCH_thread1 = (SCH_thread0<<1)/3;reg [3:0] cy_state;reg [15:0] cy_cnt;always@(posedge cy_clk,posedge cy_rst)beginif(cy_rst)begincy_cnt<=16'd0;cy_state <= 4'd0;endelsebeginif(cy_en)begincase(cy_state)4'd0:beginif(din>=SCH_thread0)begincy_state<=cy_state+4'd1;cy_cnt<=32'd0;//大于开始计时endelsebegincy_state<=cy_state;endend4'd1:begincy_cnt<=cy_cnt+32'd1;//定时器加if(din<=SCH_thread1)cy_state<=cy_state+4'd1;//大于开始计时elsecy_state<=cy_state;end4'd2:beginif(din>=SCH_thread0)begincy_state<=4'd0;//大于开始计时fre_o<=cy_cnt;endelsecy_cnt<=cy_cnt+32'd1;//定时器加endendcaseendelsebegincy_state <= cy_state;cy_cnt <= 16'd0;endendendendmodule

  在频率计模块中,SCH_thread0为施密特触发器的阈值1,阈值2为SCH_thread0的三分之一。

5.测试文件

`timescale 1ps / 1psmodule FSK_tb();reg clk;reg en;reg rst;reg de_fsk_clk;wire[7:0]dout;wire[15:0]fre_o;wire deo;reg      [7:0]         din;reg                  dqvld;//数据有效信号wire                    do;wire             send_qvld;//发送完成信号wire                 sbusy;//繁忙标志位integer i;initial beginen = 0;rst = 0;#2 rst = 1;#2 rst = 0;en = 1;i = 0;#4 din = 8'b1011_0110;while(i<50)beginwhile(sbusy == 1)begin#1 dqvld = 1'b0;end    dqvld = 1'b1;while(sbusy == 0)begin#1 dqvld = 1'b1;enddqvld = 1'b0;din = din + 1;i = i + 1;endendinitial beginde_fsk_clk = 0;forever begin#1 de_fsk_clk = ~de_fsk_clk;endendinitial beginclk = 0;forever begin#4 clk = ~clk;endendFSK_2#(. CLOCK_DIV (80)
)FSK_2_inist0(.                fsk_clk(clk),.              de_fsk_clk(de_fsk_clk),.                fsk_en(en),.                fsk_rst(rst),.                  din(din),.                dqvld(dqvld),//数据有效信号.        do(       do),.       deo(deo),.    fre_o(fre_o),.      dout(     dout),. send_qvld(send_qvld),//发送完成信号.     sbusy(    sbusy) //繁忙标志位);
endmodule

四、仿真结果

din为输入的需要发送的8位数据,dout为调制器发出的模拟波形,fre_o为频率计输出的计数值,do为转换为串行数据流的基带信号,deo为解调器解调后的数据。
基本实现了2FSK调制解调器的功能。
               图4.1 模拟波形转换图

在图4.1中由于两个载波采样点数比较相近,频率相近,所以其波形比较相似,大家也可以通过增加采样点数的方式,改变其频率。

基于verilog实现2FSK调制解调器相关推荐

  1. 基于Verilog实现2FSK调制

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 为什么要进行调制? FSK调制原理 二.调制的过程 1.M序列发生器 2.载波的实现 3.调制信号 4.wave仿真图 5. ...

  2. FPGA学习之路—应用程序—基于Verilog设计单总线8位ALU

    FPGA学习之路--基于Verilog设计单总线8位ALU 定义 ALU(arithmetic and logic unit) 算术逻辑单元,简称ALU,是计算机的数学运算核心,也就是负责运算的组件, ...

  3. 基于verilog贪吃蛇游戏设计

    概述 基于verilog贪吃蛇游戏设计.使用verilog语言 小游戏主要分为以下几个模块:顶层模块.VGA显示模块.蛇身控制模块.苹果控制模块. 系统主要分为顶层模块.VGA显示模块.蛇身控制模块. ...

  4. 基于Verilog HDL的数字时钟

    目录 一.实验目的 二.实验概述 三.实验过程 一.实验目的 1.学习相关的设计方法及原理 2.学习设计方法 二.实验概述 基于Verilog HDL设计一个时钟 三.实验过程 新建一个工程 选择芯片 ...

  5. 国产智多晶FPGA基于Verilog的设计开发流程

    大家好,我是小梅哥,这里给大家介绍国产FPGA厂家"西安智多晶"微电子的FPGA基于Verilog进行逻辑设计的开发流程,步骤详细,可作为大家的评估参考.本博客将陆续发表更多国产F ...

  6. 异步FIFO基本原理(基于Verilog的简单实现)

    参考文献: [1]彭莉, 秦建业, 付宇卓. 异步FIFO的设计与验证[J]. 计算机工程与应用, 2005, 41(3):4. [2]魏芳, 刘志军, 马克杰. 基于Verilog HDL的异步FI ...

  7. 基于Verilog的TCAM硬件实现

    **基于Verilog的TCAM硬件实现** 一. 背景 路由器是网络设备的关键组成部分,它需要接收数据包,然后决定将数据包发送到何处,以便进行IP转发或IP路由.今天的路由器需要在大量数据中进行非常 ...

  8. 基于verilog的正弦波发生器

    基于verilog的正弦波发生器 这是我在CSDN里的第一篇文章,先做个小广告.. 我建了一个嵌入式和FPGA的公众号,里面也是我写的一些文章,有的是平时学习的笔记,或者实验的记录,我希望和大家一起学 ...

  9. 基于 SoC 的卷积神经网络车牌识别系统设计(4-2)基于 Verilog 的 RGB2HSV IP 设计

    引言         这是车牌识别预处理(RGB2HSV + 二值化 + 形态学)的 IP 设计之一.主要功能是针对从 OV5640 IP 输出的 RGB888 真彩色车牌识别数据(视频传输格式:64 ...

最新文章

  1. (转载)浅析Hadoop文件格式
  2. 一个快速、高效的Levenshtein算法实现
  3. 一个插排引发的设计思想 (一) 观察者模式
  4. Python模块和包
  5. 无微不至:调整_lm_cache_res_cleanup解决Shared Pool 的4031问题
  6. 智能家居市场需求矛盾深层原因分析
  7. mybatis if-else(写法)
  8. 李宏毅机器学习(十)GPT-3
  9. Jetson Nano安装pytorch 基于torch1.6和torchvision0.7
  10. JSP学习笔记(一百一十七):Windows下nginx以服务的方式运行
  11. C语言求m以内奇数的和
  12. 【转】Java多线程编程(十)-并发编程原理(分布式环境中并发问题)
  13. 正则表达式就这么简单!
  14. 【图像分割】基于matlab超像素图像分割【含Matlab源码 720期】
  15. 助教日志—请沈航13级同学将GIT地址和CNBLOG地址发到这篇博文的评论中
  16. sublime 快捷键
  17. hadoop-uber作业模式
  18. 杰奇cms,杰奇cms程序,杰奇cms建站方法
  19. 中国人正在上的四个大当 看你到底上了几个了?
  20. 深度神经网络的应用,深度神经网络应用

热门文章

  1. C++线程池QueueUserWorkItem
  2. iOS-bug Capturing ‘self‘ strongly in this block is likely to lead to a retain cycle
  3. java小公司社招面试3则(稍微进阶)
  4. 谷歌浏览器一直转圈的问题解决
  5. 揭秘阿里巴巴物联网新零售样本-盒马鲜生
  6. 计算机在校实训项目经历,计算机实训项目.doc
  7. jpa 连接多个mysql 数据库_springboot环境jpa配置多个数据源流程
  8. ssl错误 该网站的安全证书不受信任!
  9. [Arduino]串口监视器的乱码问题
  10. 学习IOS编程必须要知道的一些知识