在采集任务里面,需要用到对一组信号进行采集,并输出平均值。通常是采用RAM表储存后再寻址累加,但对于不关注中间值,只关注平均后的值,可以直接累加后平均输出,同时输出一个分频时钟周期。
具体代码如下:
module Time_delay(
input clk,
input rst_n,
input [11:0] read_data, //输入信号
output clk_out2, //2分频
output clk_out4, //4分频
output clk_out8, //8分频
output clk_out16, //16分频
output signed [15:0] err_ave //输出的平均信号
);
reg [15:0] err_ave1;
assign err_ave = err_ave1;
reg [3:0]cnt;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 4'b1111;
else
cnt <= cnt+1;
wire signed [15:0] data;
assign data = {read_data[11:0], 4'b0000}; //扩充4位,避免小数误差被忽略
reg signed [19:0] data_ave = 20'd0;
assign clk_out2 = ~cnt[0];//根据波形,一开始全为高电平
assign clk_out4 = ~cnt[1];
assign clk_out8 = ~cnt[2];
assign clk_out16 = ~cnt[3];
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
data_ave <= 20'd0;//初始赋0
err_ave1 <= 16'd0;
end
else begin
if(cnt == 15) begin
err_ave1 <= {data_ave[19:4]};//右移4位,即为原本的1/16
data_ave <= 20'd0;
end
else begin
err_ave1 <= err_ave1;
data_ave <= data_ave + data;
end
end
endmodule
最终得到的是每16个时钟周期的平均信号,这里扩充了4位为了避免平均时小数被忽略,不需要的直接再减小4位就好了。
测试代码如下:
module Time_delay_tb();
reg clk;
reg rst_n;
reg [11:0] read_data;
wire clk_out2;
wire clk_out4;
wire clk_out8;
wire clk_out16;
wire [15:0] err_ave;
initial clk = 1;
always #10 clk = ~clk;
initial read_data = 0;
always #10 read_data = read_data + 12'd1;
initial begin
rst_n = 0;
#200;
rst_n = 1;
#20000;
$stop;
end
Time_delay Time_delay(
.clk(clk),
.rst_n (rst_n),
.clk_out2 (clk_out2),
.clk_out4 (clk_out4),
.clk_out8 (clk_out8),
.clk_out16 (clk_out16),
.read_data (read_data),
.err_ave (err_ave)
);
endmodule
仿真结果如下
时钟分频分别为2,4,8,16,输入一个步进信号,每16个周期累加,并在周期结束时输出平均值,符合设计。