`timescale 1ns / 1ps
module tops_AGC(
input i_clk,
input i_rst,
input i_flag,
input signed[11:0]i_x,
output signed[11:0]o_egy,
output signed[11:0]o_y,
output o_flag
);
//energy
wire signed[11:0]w_absx = (i_x[11] == 1'b0)?i_x:~i_x+1'b1;
integer i;
reg signed[11:0]dly_absx[2048:1];
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
for(i=1;i<=2048;i=i+1)
dly_absx[i]<=12'd0;
end
else begin
dly_absx[1]<=w_absx;
for(i=2;i<=2048;i=i+1)
dly_absx[i]<=dly_absx[i-1];
end
end
reg [23:0]power_E;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
power_E <= 24'd0;
end
else begin
power_E <= power_E + dly_absx[1]-dly_absx[2048];
end
end
assign o_egy=power_E[22:11];
//signal 延迟
reg signed[11:0]dly_x[2149:1];
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
for(i=1;i<=2149;i=i+1)
dly_x[i]<=12'd0;
end
else begin
dly_x[1]<=i_x;
for(i=2;i<=2149;i=i+1)
dly_x[i]<=dly_x[i-1];
end
end
//flag 延迟
reg signed[2148:0]dly_flag;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
dly_flag<=2149'd0;
end
else begin
dly_flag<={dly_flag[2147:0],i_flag};
end
end
wire signed[11:0]w_y = dly_x[2149];
assign o_flag= dly_flag[2048];
//自动增益
wire [19 : 0] gains;
blk_agc blk_agc_u (
.clka(i_clk), // input wire clka
.rsta(i_rst), // input wire rsta
.addra(o_egy), // input wire [8 : 0] addra
.douta(gains), // output wire [19 : 0] douta
.rsta_busy() // output wire rsta_busy
);
reg signed[19:0]wgains;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
wgains <= 20'b0;
end
else begin
if(o_flag == 1'b1)
wgains <= gains;
else
wgains <= wgains;
end
end
reg signed[31:0]r_pw;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
r_pw <= 32'b0;
end
else begin
r_pw <= $signed(wgains)*$signed(w_y);
end
end
assign o_y=r_pw[31-12:20-12];
endmodule
测试代码:
`timescale 1ns / 1ps
module tops_AGC(
input i_clk,
input i_rst,
input i_flag,
input signed[11:0]i_x,
output signed[11:0]o_egy,
output signed[11:0]o_y,
output o_flag
);
//energy
wire signed[11:0]w_absx = (i_x[11] == 1'b0)?i_x:~i_x+1'b1;
integer i;
reg signed[11:0]dly_absx[2048:1];
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
for(i=1;i<=2048;i=i+1)
dly_absx[i]<=12'd0;
end
else begin
dly_absx[1]<=w_absx;
for(i=2;i<=2048;i=i+1)
dly_absx[i]<=dly_absx[i-1];
end
end
reg [23:0]power_E;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
power_E <= 24'd0;
end
else begin
power_E <= power_E + dly_absx[1]-dly_absx[2048];
end
end
assign o_egy=power_E[22:11];
//signal 延迟
reg signed[11:0]dly_x[2149:1];
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
for(i=1;i<=2149;i=i+1)
dly_x[i]<=12'd0;
end
else begin
dly_x[1]<=i_x;
for(i=2;i<=2149;i=i+1)
dly_x[i]<=dly_x[i-1];
end
end
//flag 延迟
reg signed[2148:0]dly_flag;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
dly_flag<=2149'd0;
end
else begin
dly_flag<={dly_flag[2147:0],i_flag};
end
end
wire signed[11:0]w_y = dly_x[2149];
assign o_flag= dly_flag[2048];
//自动增益
wire [19 : 0] gains;
blk_agc blk_agc_u (
.clka(i_clk), // input wire clka
.rsta(i_rst), // input wire rsta
.addra(o_egy), // input wire [8 : 0] addra
.douta(gains), // output wire [19 : 0] douta
.rsta_busy() // output wire rsta_busy
);
reg signed[19:0]wgains;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
wgains <= 20'b0;
end
else begin
if(o_flag == 1'b1)
wgains <= gains;
else
wgains <= wgains;
end
end
reg signed[31:0]r_pw;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
r_pw <= 32'b0;
end
else begin
r_pw <= $signed(wgains)*$signed(w_y);
end
end
assign o_y=r_pw[31-12:20-12];
endmodule
用到了DDS和ROM IP核。