liu672992381 发表于 2018-10-3 20:47:35

CPLD移频键控(FSK),请教频率切换问题

   最近在研究移频键控(FSK)。原理是:用低频的“1”发送高频,用低频的“0”发送低频(本质就是发送疏密波)。
我用CPLD产生了准确的高、低频率,问题出在:
    1、高、低频率切换时出现一个幅度不一样的方波。
    2、载频信号中有梯形波出现,正常应该都是完整的方波。

希望各位坛友,能帮忙看看程序,指出问题。代码如下:

module fsk(out,led,clk,key,beep,beep1);// 模块名及端口参数

input clk;                                        //输入端口定义,50M 时钟
input key;                                //调制用的低频信号
output        out;                                //载频输出端
output led;                                // 输出端口定义,6位二进制数,初始状态全部为“1”
output        beep;                        //低频频率输出
output        beep1;                        //高频频率输出

reg beep_r;                                                //寄存器                                               
reg beep_r1;                                        //寄存器
reg out;

reg led;                                        //变量led_out 定义为寄存器型
reg counter;                        //变量led_out 定义为寄存器型
reg psk;                                        //变量led_out 定义为寄存器型
reg psk1;                                //变量led_out 定义为寄存器型

assign beep = beep_r;                //脉冲输出
assign beep1 = beep_r1;                //脉冲输出

always@(posedge clk)    //有时钟上升沿时,
begin                                                        //
               
counter<=counter+1;        //工作指示灯
        if(counter==25'd25000000)//如果到了0.5s则begin程序,d'25表示25位十进制数字
        begin
       
        led<=1;                                // 熄灭LED灯,Verilog 中操作位是用"[]",c中是用"^".
        counter<=0;                                //计数器清0
        if(led==1)                        //
        led<=0;                                //点亮LED
end
       
end

always@(posedge clk)    //当有时钟上升沿时
begin                                                        //
        psk1<=psk1+1;
        psk<=psk+1;
        if(psk==25'd14784)//如果到十进制数字--d14784
        begin                                        //输出低频率信号
       
        beep_r<=1;                        //
        psk<=0;                                //计数器清0
        if(beep_r==1)                //
        beep_r<=0;                        //
        end
       
        if(psk1==25'd14620)//如果到十进制数字---d14620
        begin                                        //输出高频率信号                       

        beep_r1<=0;                        //
        psk1<=0;                                //计数器清0
        if(beep_r1==0)                //
        beep_r1<=1;                        //
        end
       
       
end

always@(key)                        //按键切换,高低频信号输出
        begin
                if(key)out = beep_r1;        //输出高频率信号
                else out = beep_r;                //输出低频率信号
        end

endmodule
       

chenchaoting 发表于 2018-10-3 20:58:11

没看程序,直接切换必然会有这样的问题啊,因为他们的相位不连续

liu672992381 发表于 2018-10-3 22:47:41

chenchaoting 发表于 2018-10-3 20:58
没看程序,直接切换必然会有这样的问题啊,因为他们的相位不连续

不知道,怎么切换好。

NJ8888 发表于 2018-10-4 07:19:28

应该是同一端口输出可变高低频,不能用直接切换,而这高低频都是与载频同边沿开始,就是载频是高频低频的公倍数

1a2b3c 发表于 2018-10-4 08:44:58

最好是用cpfsk

XA144F 发表于 2018-10-4 09:11:50

fsk频率和码率有严格的关系,简单说就是频率是码率的整数倍,这样才能保证在0度位置才切换。

xyz543 发表于 2018-10-4 12:20:50

上 DDS 吧!

liu672992381 发表于 2018-10-4 20:42:45

XA144F 发表于 2018-10-4 09:11
fsk频率和码率有严格的关系,简单说就是频率是码率的整数倍,这样才能保证在0度位置才切换。 ...

FSK和码率,没有比例关系。就是在频率切换时出问题了。

liu672992381 发表于 2018-10-4 20:44:32

xyz543 发表于 2018-10-4 12:20
上 DDS 吧!

求教,有什么好的DDS芯片或者模块推荐吗?

liu672992381 发表于 2018-10-4 20:46:40

1a2b3c 发表于 2018-10-4 08:44
最好是用cpfsk

有没有推荐的模块,没有接触过,怕入坑。

liu672992381 发表于 2018-10-4 20:49:32

NJ8888 发表于 2018-10-4 07:19
应该是同一端口输出可变高低频,不能用直接切换,而这高低频都是与载频同边沿开始,就是载频是高频低频的公 ...

刚刚接触,不是很懂,我在10楼发了一个载频相关的图片。没有看出载频是高低频的公倍数,请您帮忙分析。

XA144F 发表于 2018-10-4 21:28:53

dds的话用ad9854或者ad9910就能轻松的产生fsk或者psk。

liu672992381 发表于 2018-10-4 21:42:43

XA144F 发表于 2018-10-4 21:28
dds的话用ad9854或者ad9910就能轻松的产生fsk或者psk。

    这么高频率,实现2KHZ的FSK,会不会大材小用了。最主要,我怕两三天时间搞不定。

laotui 发表于 2018-10-4 23:00:49

时间有点久了,以前做过一次,主要为了验证解调写了一个简单的调制部分,有一个写报告时的截图留下来了。

zhangalex88 发表于 2018-10-4 23:44:07

将后面两个always代码段,改为以下代码试试:
always@(posedge clk)    //当有时钟上升沿时
begin                                                      //
      psk<=psk+1;
      if((psk==25'd14784)||((psk==25'd14620)&&key))//Key为0,输出低频率信号,当Key为1时,到计数点完成计数后再输出高频信号,
      begin                                        //
      beep_r<=1;                        //
      psk<=0;                              //计数器清0
      if(beep_r==1)                //
      beep_r<=0;                        //
      end
end
assign out=beep_r;

dellric 发表于 2018-10-4 23:51:49

module fsk(out,led,clk,key,beep,beep1);// 模块名及端口参数

        input clk;                                        //输入端口定义,50M 时钟
        input key;                              //调制用的低频信号
        output      out;                              //载频输出端
        output led;                              // 输出端口定义,6位二进制数,初始状态全部为“1”
        output      beep;                        //低频频率输出
        output      beep1;                        //高频频率输出

        reg beep_r;                                                //寄存器                                                
        reg beep_r1;                                        //寄存器
        reg out;

        reg led;                                        //变量led_out 定义为寄存器型
        reg counter;                        //变量led_out 定义为寄存器型
        reg psk;                                        //变量led_out 定义为寄存器型
        reg psk1;                              //变量led_out 定义为寄存器型

        assign beep = beep_r;                //脉冲输出
        assign beep1 = beep_r1;                //脉冲输出
        assign out = (key ) ? beep_r1:beep_r;

        always@(posedge clk)   begin //有时钟上升沿时,
                if(counter==(25'd25000000 -1 ))begin
                        counter <= 25'd0;
                        led <= ~ led;
                end
                else begin
                        counter <= counter + 1'b1;
                end
        end

        always@(posedge clk)   begin//当有时钟上升沿时
                if ( psk == 25'd14716 ) begin // 1698.7 Hz
                        psk <= 25'd0;
                        beep_r <= ~beep_r;
                end
                else begin
                        psk <= psk + 1'b1;
                end
               
                if ( psk1 == 25'd14693 ) begin // 1701.4Hz
                        psk1 <= 25'd0;
                        beep_r1 <= ~beep_r1;
                end
                else begin
                        psk1 <= psk1 + 1'b1;
                end
        end

endmodule

dellric 发表于 2018-10-4 23:53:08

帮你把程序修改了一下,看程序应该不是产生阶梯波的关键,请仔细检查是否你的key输入是正确的,直接给高电平或低电平看看结果

dellric 发表于 2018-10-3 20:47:36

//你的程序写得太麻烦了,我帮你修改了一下,简化了很多,你试试看,有结果了请贴个图上来
module fsk(out,led,clk,key);// 模块名及端口参数

        inputclk;                                        //输入端口定义,50M 时钟
        inputkey;                              //调制用的低频信号
        output regout;                              //载频输出端
        output regled;                              // 输出端口定义,6位二进制数,初始状态全部为“1”

        reg counter;                        //变量led_out 定义为寄存器型
        reg psk;                                        //变量led_out 定义为寄存器型

        always@(posedge clk)   begin //有时钟上升沿时,
                if(counter==(25'd24999999 ))begin
                        counter <= 25'd0;
                        led<= ~ led ;
                end
                else begin
                        counter <= counter + 1'b1;
                end
        end

        always@(posedge clk)   begin//当有时钟上升沿时
                if ( key == 1 ) begin
                        psk <= psk + 27'd4567;
                end
                else begin
                        psk <= psk + 27'd4560;
                end
                out <= psk;
        end

endmodule

zhangalex88 发表于 2018-10-5 00:14:15

本帖最后由 zhangalex88 于 2018-10-5 00:42 编辑

按我的自己的习惯,后面2段always我会写成:
reg out;
always@(posedge clk)    //当有时钟上升沿时
begin                                                      //
      if((psk==25'd14784)||((psk==25'd14620)&&key))//Key为0,输出低频率信号,当Key为1时,到计数点完成计数后再输出高频信号
      begin                                        //
      psk<=0;                              //计数器清0
      out<=~out;                        //反向输出
      end
      else
      psk<=psk+1;
end

dellric 发表于 2018-10-5 00:58:47

本帖最后由 dellric 于 2018-10-5 01:05 编辑

zhangalex88 发表于 2018-10-5 00:14
按我的自己的习惯,后面2段always我会写成:
reg out;
always@(posedge clk)    //当有时钟上升沿时


楼主的载波分频比好像是计算错的

liu672992381 发表于 2018-10-5 07:57:39

dellric 发表于 2018-10-5 00:13
//你的程序写得太麻烦了,我帮你修改了一下,简化了很多,你试试看,有结果了请贴个图上来
module fsk(out, ...

    陈独秀、帝华之秀......请收下我的膝盖。用了你的程序,真的没有梯形波了,我这个小菜鸡没看懂你的程序。
能简单帮忙解析一下,或者添加一些注释。小弟感激不尽,这难道就是国庆节的大礼,哈哈。

liu672992381 发表于 2018-10-5 07:58:17

zhangalex88 发表于 2018-10-5 00:14
按我的自己的习惯,后面2段always我会写成:
reg out;
always@(posedge clk)    //当有时钟上升沿时


   用楼上的程序,解决了。稍后试您的程序。

liu672992381 发表于 2018-10-5 07:59:30

dellric 发表于 2018-10-5 00:58
楼主的载波分频比好像是计算错的

   频偏11HZ,我计算的确实有误,这都被您看出来了,真的细致。

liu672992381 发表于 2018-10-5 08:08:50

dellric 发表于 2018-10-4 23:51
module fsk(out,led,clk,key,beep,beep1);// 模块名及端口参数

        input clk;                              ...

这个代码编译的时候出现了三个错误。
Error (10219): Verilog HDL Continuous Assignment error at led_water.v(27): object "out" on left-hand side of assignment must have a net type
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 1 error, 0 warnings
        Error: Peak virtual memory: 312 megabytes
        Error: Processing ended: Fri Oct 05 08:05:33 2018
        Error: Elapsed time: 00:00:01
        Error: Total CPU time (on all processors): 00:00:01
Error: Quartus II Full Compilation was unsuccessful. 3 errors, 0 warnings

我不知道怎么改,双击后指示的是这行代码      assign out = (key ) ? beep_r1:beep_r;

liu672992381 发表于 2018-10-5 08:33:20

zhangalex88 发表于 2018-10-5 00:14
按我的自己的习惯,后面2段always我会写成:
reg out;
always@(posedge clk)    //当有时钟上升沿时


添加这个always程序,注释掉两个always。高低电平受key控制。
1、当key为低时,out引脚有准确的方波输出,而且实现了频率的切换,示波器上能看出明暗不同的波形(这个示波器是学校很古董的了)。
2、当key为高时,out引脚一段时间一直是高电平,或者低电平,紧跟着有不同频率的方波切换(现象和key为低一样)。

如果想到怎么修改,我继续测试。哈哈,非常感谢你的帮忙。

XA144F 发表于 2018-10-5 08:46:39

这很好理解吧,信号的电平切换时,频率的电平不能立即跟着变化,而是要等到这个周期结束后才变,这样才保证波形连续没有突变。

zhangalex88 发表于 2018-10-5 10:10:08

liu672992381 发表于 2018-10-5 08:33
添加这个always程序,注释掉两个always。高低电平受key控制。
1、当key为低时,out引脚有准确的方波输出 ...

我用完整代码测试了一下,没有发现问题:
module fsk(out,clk,key);// 模块名及端口参数
input clk,key;                                        //输入端口定义,50M 时钟
output reg out;                              //载频输出端
reg psk;                                        //变量led_out 定义为寄存器型

always@(posedge clk)    //当有时钟上升沿时
begin                                                      //
      if((psk==25'd14784)||((psk==25'd10000)&&key))//Key为0,输出低频率信号,当Key为1时,到计数点完成计数后再输出高频信号
      begin                                        //
      psk<=0;                              //计数器清0
      out<=~out;                        //反向输出
      end
      else
      psk<=psk+1;
end

endmodule
注:为了好观察,高频计数器值我改为了25'd10000

dellric 发表于 2018-10-5 10:17:14

liu672992381 发表于 2018-10-5 08:08
这个代码编译的时候出现了三个错误。
Error (10219): Verilog HDL Continuous Assignment error at led_w ...

reg out;
把这行注释掉看看

dellric 发表于 2018-10-5 10:27:39

liu672992381 发表于 2018-10-5 07:57
陈独秀、帝华之秀......请收下我的膝盖。用了你的程序,真的没有梯形波了,我这个小菜鸡没看懂你的程 ...

你看是哪个程序的那个部分看不懂?两个程序都很简单,你稍微分析一下应该没有问题的。

liu672992381 发表于 2018-10-5 11:44:00

dellric 发表于 2018-10-5 10:27
你看是哪个程序的那个部分看不懂?两个程序都很简单,你稍微分析一下应该没有问题的。 ...

always@(posedge clk)   begin//当有时钟上升沿时
                if ( key == 1 ) begin
                        psk <= psk + 27'd4567;
                end
                else begin
                        psk <= psk + 27'd4560;
                end
                out <= psk;
      end

这部分看不懂,不知道怎么实现的。希望您帮忙解析。

1、为什么用psk <= psk + 27'd4567;
2、为什么是27'd4567,
3、为什么是 out <= psk;这么快就实现了频率的切换,实在看不明白。

我刚学的CPLD,也就10天左右的时间,只会一些基本的语法而已。

liu672992381 发表于 2018-10-5 12:02:43

zhangalex88 发表于 2018-10-5 10:10
我用完整代码测试了一下,没有发现问题:
module fsk(out,clk,key);// 模块名及端口参数
input clk,key;...

刚刚试验了,不加给key加信号,就是是正常的切换频率。

liu672992381 发表于 2018-10-5 12:04:28

zhangalex88 发表于 2018-10-5 10:10
我用完整代码测试了一下,没有发现问题:
module fsk(out,clk,key);// 模块名及端口参数
input clk,key;...

示波器比较老了,只能暂停看到这样的波形。

liu672992381 发表于 2018-10-5 12:10:03

dellric 发表于 2018-10-5 10:17
reg out;
把这行注释掉看看

注释掉这一行,编译通过了,但是有梯形波出现。和我写的那个程序一样了。

liu672992381 发表于 2018-10-5 12:19:11

XA144F 发表于 2018-10-5 08:46
这很好理解吧,信号的电平切换时,频率的电平不能立即跟着变化,而是要等到这个周期结束后才变,这样才保证 ...

      是的,确实是您说的这样。我用坛友的程序,功能确实实现了,只是检测到的调制频率,比如16.9HZ会不断的变化,这可能就是相位不同导致的。
我这半生不熟的,想再了解的更深一点。写出稳定的程序,看来有很大的困难。

liu672992381 发表于 2018-10-5 12:20:18

laotui 发表于 2018-10-4 23:00
时间有点久了,以前做过一次,主要为了验证解调写了一个简单的调制部分,有一个写报告时的截图留下来了。
...

还能帮忙找找,你写的程序吗?

dellric 发表于 2018-10-5 16:40:22

本帖最后由 dellric 于 2018-10-5 16:41 编辑

liu672992381 发表于 2018-10-5 11:44
always@(posedge clk)   begin//当有时钟上升沿时
                if ( key == 1 ) begin
      ...

n= 2^N * f / fs
fs = 50000000;
f = 希望得到的频率
N = 计数器位数

liu672992381 发表于 2018-10-5 20:52:37

dellric 发表于 2018-10-5 16:40
n= 2^N * f / fs
fs = 50000000;
f = 希望得到的频率


好的,看懂了,若是频率有小数点,用这个公式也可以吗?

huangqi412 发表于 2018-10-5 21:14:17

这个梯形好宽

dellric 发表于 2018-10-5 21:31:15

liu672992381 发表于 2018-10-5 20:52
好的,看懂了,若是频率有小数点,用这个公式也可以吗?

是的,专治小数点,你试试先,记得发图大家共享

liu672992381 发表于 2018-10-5 22:15:36

dellric 发表于 2018-10-5 21:31
是的,专治小数点,你试试先,记得发图大家共享

   好的,这个没问题,我明天试一试2000的频率,示波器太烂。学校的老古董了,哈哈哈。

liu672992381 发表于 2018-10-5 22:17:43

zhangalex88 发表于 2018-10-5 10:10
我用完整代码测试了一下,没有发现问题:
module fsk(out,clk,key);// 模块名及端口参数
input clk,key;...

   能教教我怎么仿真吗?菜鸡想学,有没有一些仿真说明手册。感觉开发环境和C太不一样了,一下子适应不了。

zhangalex88 发表于 2018-10-5 22:32:17

liu672992381 发表于 2018-10-5 22:17
能教教我怎么仿真吗?菜鸡想学,有没有一些仿真说明手册。感觉开发环境和C太不一样了,一下子适应不了 ...

我这个不是仿真,手头正好有搭好的环境,就验证了一下代码,截图是实际的输出,用逻辑分析仪抓到的波形。
仿真找本书看看,对着敲几个例子,很快就可以上手的。
简单和前期的验证写测试模块还好,后期有硬件了,我都是直接在板上验证,写测试模块有时反而繁琐了。

dellric 发表于 2018-10-5 23:01:44

liu672992381 发表于 2018-10-5 22:15
好的,这个没问题,我明天试一试2000的频率,示波器太烂。学校的老古董了,哈哈哈。 ...

还在读书吗?国庆没有回家看望爹妈?

qiqirachel 发表于 2018-10-5 23:15:02

FSK翻译成平移建控,感觉上是超级的蛋疼

liu672992381 发表于 2018-10-6 06:35:07

dellric 发表于 2018-10-5 23:01
还在读书吗?国庆没有回家看望爹妈?

参加工作了(在职研究生,不算在读书吧),给老师做的课题,国庆节都在学校,做这个。课题结束就休假。

liu672992381 发表于 2018-10-6 06:36:17

qiqirachel 发表于 2018-10-5 23:15
FSK翻译成平移建控,感觉上是超级的蛋疼

我也是按照,键控的概念去实现的。有没有正确点的翻译。

liu672992381 发表于 2018-10-6 12:44:11

qiqirachel 发表于 2018-10-5 23:15
FSK翻译成平移建控,感觉上是超级的蛋疼

设置频率为2000HZ的时候,一直不准。不知道什么原因。

liu672992381 发表于 2018-10-6 15:35:56

dellric 发表于 2018-10-5 21:31
是的,专治小数点,你试试先,记得发图大家共享

下面这段代码不知道哪里有问题,频率切换除了1,以外都是错的。能帮我看看吗?
是不是用if begin 是顺序执行,用forking并行执行要好一些?低频经常会有细微的变化。就是这一句,psk <= psk + addL;//

                  input data;                                        //选择频率
//                  output add;                                        //指示是否接收到频率切换
                  reg addL;                                                //定义一个低频数值
                  reg addH;                                                //定义一个低频数值

always @ (data)
                        begin case (data)
                        4'b0001 : begin                        //1
                                addL <= 27'd4540;
                                addH <= 27'd4597;                //
                        end
                        4'b0010 : begin                        //2
                                addL <= 27'd5337;
                                addH <= 27'd5402;                //
                        end
                        4'b0100 : begin                        //3
                                addL <= 27'd6144;
                                addH <= 27'd6207;                //
                        end
                        4'b1000 : begin                        //4
                                addL <= 27'd6947;
                                addH <= 27'd7013;                //
                        end
                        default : begin                        //默认1
                                addL <= 27'd4540;
                                addH <= 27'd4597;                //
                        end
               
                endcase
end
                        always@(posedge clk)   begin//当有时钟上升沿时
                if ( key == 1 ) begin
                                                                        psk <= psk + addL;//
                                               end
                                               else begin
                                                                        psk <= psk + addH;        //
                                               end                                                
                                               out <= psk;                                                                                      
                                       end

dellric 发表于 2018-10-6 16:07:24

liu672992381 发表于 2018-10-6 15:35
下面这段代码不知道哪里有问题,频率切换除了1,以外都是错的。能帮我看看吗?
是不是用if begin 是顺序 ...

你这个简单,全部写到always@(posedge clk) 里面去

liu672992381 发表于 2018-10-16 10:40:00

dellric 发表于 2018-10-6 16:07
你这个简单,全部写到always@(posedge clk) 里面去

   全部写在一个always@(posedge clk) 里,也不行。找不到好的方法了。不知道错在哪里,代码如下:

always@(posedge clk)   begin//当有时钟上升沿时
                                             case (data)
                                        4'b0001 : begin                        //1
                                                          addL <= 27'd4540;
                                                          addH <= 27'd4597;                //
                                        end
                                        4'b0010 : begin                        //2
                                                          addL <= 27'd5337;
                                                          addH <= 27'd5402;                //
                                        end
                               
                                        default : begin                        //默认1
                                                          addL <= 27'd4540;
                                                          addH <= 27'd4597;                //
                                        end
                                       endcase
                                       
                                if ( key == 1 ) begin
                                                        psk1 <= psk1 + addL;//1690.4左右 对应的值27'd4485
                               end
                               else begin
                                                        psk1 <= psk1 + addH;        //灯不亮,1712.53 对应的值27'd4597   d5477
                               end                                                
                               out <= psk1;
       end
页: [1]
查看完整版本: CPLD移频键控(FSK),请教频率切换问题