2ASK调试模式比较简单,就是用有信号和没有信号来表示0,1。现在问题就是如何从基带层面判断一个信号是有还是没有。当然是通过幅度。我们做一个模块算出波谷的绝对值,和波峰相加就得到了幅度。之后设置两个阈值,大于这个阈值1就认为是数值1,小于阈值0就认为是数值0,而在0,1之间的就保持之前的数值状态。
module amp_cal(
input clk ,
input [11:0] adc_value ,
output reg [12:0] result,
output reg valid
);
reg [11:0] trough,hill ,adc_value_r;
reg [11:0] abs_value ,abs_flag;
// stage 1
always @ (posedge clk )adc_value_r<=adc_value;
//stage 2
always @ (posedge clk) if (adc_value_r[11]) abs_value <= ~adc_value_r + 1 ; else abs_value <= adc_value_r ;
always @ (posedge clk) abs_flag <= adc_value_r[11] ;
//stage 3
reg abs_flagr ;
always @ (posedge clk) abs_flagr <= abs_flag ;wire fall_cross_zero = {abs_flagr,abs_flag} ==2'b01;
always @ (posedge clk)if (fall_cross_zero) trough<=0; else if (abs_flag) if (trough < abs_value) trough <= abs_value;
always @ (posedge clk)if (fall_cross_zero) hill<=0; else if (~abs_flag) if (hill < abs_value) hill <= abs_value;
//stage 4
always @(posedge clk) if (fall_cross_zero) result <= trough + hill ;
always @(posedge clk) valid <= fall_cross_zero;
endmodule
代码按照流水线方式写的,为了更好理解代码,看下面这个图:

波峰hill,波谷trough,从波峰降低到波谷穿越0点时候我们叫做fall_cross_zero。我fall_cross_zero时候我们看到hill和trough都已经算出来好了(都是正数,其中trough是波谷的绝对值),我们在fall_cross_zero是计算出来hill+trough就得到这这个周期的振幅。同时在fall_cross_zero时候清零波峰和波谷最大值保存器。
这里用流水线形式来写出发点不是为了考虑速度,而是有些运算为了让编译器搞明白(或者说为了让我们说明白,而不至于让编译器优化掉)多加寄存器的写法还是很可取的。
这个应该没有必要仿真的,想出错都难。
我们这里认为振幅超过一定的限度就是收到为了信号。但是这里存在一个问题,如下图表示:

在这例子里面,始终没有穿越0点,这样也就时钟算不出来一个result 。所以这时候我们应该再加上一个超时计数器,类似看门狗吧。当超过一定时间没有valid产生,他就产生一个复位信号清除result 输出0.这个超时的数值我们希望能可以设置,于是代码可以这样改写:
/*
amp_cal_with_dog amp_cal_with_dog (
.clk( ),
.adc_value( ) ,
.result( ),
.valid( ) ,
.time_of_value( )
);
*/
module amp_cal_with_dog (input clk ,
input [11:0] adc_value ,
output reg [12:0] result,
output reg valid ,
input [15:0]time_of_value
);
wire [15:0] time_out_value_r ;
synchronizer #(.WIDTH ( 1 )) syn_time_of_value ( .clk(clk), .in(time_of_value), .out(time_of_value_r));
reg [15:0] cnt;
reg [11:0] trough,hill ,adc_value_r;
reg [11:0] abs_value ,abs_flag;
//stage 1
always @ (posedge clk )adc_value_r<=adc_value;
//stage 2
always @ (posedge clk) if (adc_value_r[11]) abs_value <= ~adc_value_r + 1 ; else abs_value <= adc_value_r ;
always @ (posedge clk) abs_flag <= adc_value_r[11] ;
//stage 3
reg abs_flagr ;
always @ (posedge clk) abs_flagr <= abs_flag ;wire fall_cross_zero = {abs_flagr,abs_flag} ==2'b01;
always @ (posedge clk)if (fall_cross_zero) trough<=0; else if (abs_flag) if (trough < abs_value) trough <= abs_value;
always @ (posedge clk)if (fall_cross_zero) hill<=0; else if (~abs_flag) if (hill < abs_value) hill <= abs_value;
//stage 4
wire cnt_overflow = cnt == time_of_value_r ;
always @(posedge clk) if (fall_cross_zero | cnt_overflow )cnt<=0;else cnt<=cnt+1;
always @(posedge clk) if ( cnt_overflow) result<=0;else if (fall_cross_zero) result <= trough + hill ;
always @(posedge clk) valid <= fall_cross_zero | cnt_overflow ;
endmodule
至于这个time_of_value如何设置呢,我认为设置1.5倍的周期就可以了。比方DDS出一个完整的波形用的点数是36,我们可以设置time_of_value为54 就可以。这里注意of是overflow的简写。
OK这个模块写好了,再继续琢磨下要做什么。

2279

被折叠的 条评论
为什么被折叠?



