(四)FIR滤波器Verilog代码设计
顶层模块设计:
module FIR_48k(
CLK,
RESET,
DATA_IN,
EN,
DATA_OUT,
OE,
CLK_OUT
);
input CLK;
input RESET;
input [7:0] DATA_IN;
input EN;
output [15:0] DATA_OUT;
output OE;
output CLK_OUT;
wire [7:0] ADDR_DATA_W;
wire DATA_WE;
wire [7:0] ADDR_DATA_R;
wire [6:0] ADDR_COEF_R;
wire OE_ac;
wire DATA_FIRST;
wire DATA_LAST;
wire [7:0] DATA;
wire [15:0] COEF;
addr_control ac1(
.CLK(CLK),
.RESET(RESET),
.EN(EN),
.ADDR_DATA_W(ADDR_DATA_W),
.DATA_WE(DATA_WE),
.ADDR_DATA_R(ADDR_DATA_R),
.ADDR_COEF_R(ADDR_COEF_R),
.OE(OE_ac),
.DATA_FIRST(DATA_FIRST),
.DATA_LAST(DATA_LAST)
);
data_ram dr1(
.WE(DATA_WE),
.WCLK(CLK),
.RCLK(CLK),
.ADDRW(ADDR_DATA_W),
.ADDRR(ADDR_DATA_R),
.DATAW(DATA_IN),
.DATAR(DATA)
);
rom_coef rc1(
.CLK(CLK),
.ADDRESS(ADDR_COEF_R),
.DOUT(COEF)
);
conv c1(
.CLK(CLK),
.RESET(RESET),
.EN(OE_ac),
.DATA_IN(DATA),
.COEF(COEF),
.DATA_FIRST(DATA_FIRST),
.DATA_LAST(DATA_LAST),
.SUM_OUT(DATA_OUT),
.SOE(OE),
.CLKOUT(CLK_OUT)
);
endmodule
地址控制器设计,用于控制送入卷积器中的数据:
module addr_control(
CLK,
RESET,
EN,
ADDR_DATA_W,
DATA_WE,
ADDR_DATA_R,
ADDR_COEF_R,
OE,
DATA_FIRST,
DATA_LAST
);
input CLK,RESET,EN;
output [7:0] ADDR_DATA_W;
output DATA_WE;
output [7:0] ADDR_DATA_R;
output [6:0] ADDR_COEF_R;
output OE;
output DATA_FIRST,DATA_LAST;
reg [7:0] ADDR_DATA_W;
reg [7:0] ADDR_DATA_R;
reg [6:0] ADDR_COEF_R;
reg OE;
reg DATA_FIRST,DATA_LAST;
//reg [7:0] cnt_data_w;
reg [7:0] cnt_data_r;
reg [7:0] cnt_data_fr;
reg [6:0] cnt_coef_r;
reg cnt_coef_r_ud;
reg [7:0] cnt_in;
reg dedoe0,dedoe1;
reg dedfirst0,dedfirst1;
reg dedlast0,dedlast1;
reg [1:0] state;
parameter IDLE = 2'b00 , DATA_INPUT = 2'b01 , DATA_READ = 2'b10 , CONV_FINISH = 2'b11;
assign DATA_WE = EN;
always @ (posedge CLK or negedge RESET)
begin
if(!RESET)
begin
ADDR_DATA_R <= 8'd0;
ADDR_COEF_R <= 7'd0;
OE <= 1'b0;
DATA_FIRST <= 1'b0;
DATA_LAST <= 1'b0;
dedoe1 <= 1'b0;
dedfirst1 <= 1'b0;
dedlast1 <= 1'b0;
end
else
begin
ADDR_DATA_R <= cnt_data_r;
ADDR_COEF_R <= cnt_coef_r;
OE <= dedoe1;
DATA_FIRST <= dedfirst1;
DATA_LAST <= dedlast1;
dedoe1 <= dedoe0;
dedfirst1 <= dedfirst0;
dedlast1 <= dedlast0;
end
end
always @ (posedge CLK or negedge RESET)
begin
if(!RESET)
begin
state <= IDLE;
//cnt_data_w <= 8'd0;
ADDR_DATA_W <= 8'd0;
cnt_in <= 8'd0;
cnt_data_fr <= 8'd0;
cnt_data_r <= 8'd0;
cnt_coef_r <= 8'd0;
cnt_coef_r_ud <= 1'b0;
dedoe0 <= 1'b0;
dedfirst0 <= 1'b0;
dedlast0 <= 1'b0;
end
else
begin
case(state)
IDLE :
begin
if(EN)
begin
ADDR_DATA_W <= add_mod(ADDR_DATA_W , 8'd1);
//ADDR_DATA_W <= cnt_data_w;
cnt_in <= cnt_in + 1;
cnt_data_fr <= 8'd0;
cnt_data_r <= 8'd0;
cnt_coef_r <= 8'd0;
dedoe0 <= 1'b0;
dedfirst0 <= 1'b0;
dedlast0 <= 1'b0;
state <= DATA_INPUT;
end
end
DATA_INPUT :
begin
if(EN)
begin
ADDR_DATA_W <= add_mod(ADDR_DATA_W , 8'd1);
//ADDR_DATA_W <= cnt_data_w;
if(cnt_in < 8'd241)
begin
cnt_in <= cnt_in + 1;
cnt_data_fr <= 8'd0;
end
else
begin
cnt_in <= 8'd242;
cnt_data_fr <= add_mod(cnt_data_fr , 8'd1);
cnt_data_r <= cnt_data_fr;
cnt_coef_r <= 8'd0;
dedoe0 <= 1'b1;
dedfirst0 <= 1'b1;
dedlast0 <= 1'b0;
state <= DATA_READ;
end
end
end
DATA_READ :
begin
if(cnt_data_r == sub_mod(cnt_data_fr , 8'd2))
begin
cnt_coef_r_ud <= 1'b0;
dedoe0 <= 1'b0;
dedfirst0 <= 1'b0;
dedlast0 <= 1'b0;
state <= CONV_FINISH;
end
else
begin
dedoe0 <= 1'b1;
dedfirst0 <= 1'b0;
if(cnt_data_r == sub_mod(cnt_data_fr , 8'd3))
dedlast0 <= 1'b1;
cnt_data_r <= add_mod(cnt_data_r , 8'd1);
if(!cnt_coef_r_ud)
begin
if(cnt_coef_r == 7'd120)
begin
cnt_coef_r <= cnt_coef_r;
cnt_coef_r_ud <= 1'b1;
end
else
cnt_coef_r <= add_mod_coef(cnt_coef_r , 7'd1);
end
else
cnt_coef_r <= sub_mod_coef(cnt_coef_r , 7'd1);
end
end
CONV_FINISH :
begin
if(EN)
begin
ADDR_DATA_W <= add_mod(ADDR_DATA_W , 8'd1);
//ADDR_DATA_W <= cnt_data_w;
cnt_data_fr <= add_mod(cnt_data_fr , 8'd1);
cnt_data_r <= cnt_data_fr;
cnt_coef_r <= 8'd0;
dedoe0 <= 1'b1;
dedfirst0 <= 1'b1;
dedlast0 <= 1'b0;
state <= DATA_READ;
end
end
default :
state <= IDLE;
endcase
end
end
function [6:0] add_mod_coef;
input [6:0] a;
input [6:0] b;
reg[7:0] c, t;
begin
c = a + b;
if(c >= 121) begin
t = c - 121;
add_mod_coef = t[6:0];
end
else
add_mod_coef = c[6:0];
end
endfunction // function add_mod_coef
function [6:0] sub_mod_coef;
input [6:0] a;
input [6:0] b;
reg[7:0] c;
begin
c = 121 + a - b;
if(c >= 121)
begin
c = c - 121;
sub_mod_coef = c[6:0];
end
else
sub_mod_coef = c[6:0];
end
endfunction // function sub_mod_coef
function [7:0] add_mod;
input [7:0] a;
input [7:0] b;
reg[8:0] c, t;
begin
c = a + b;
if(c >= 242) begin
t = c - 242;
add_mod = t[7:0];
end
else
add_mod = c[7:0];
end
endfunction // function add_mod
function [7:0] sub_mod;
input [7:0] a;
input [7:0] b;
reg[8:0] c;
begin
c = 242 + a - b;
if(c >= 242)
begin
c = c - 242;
sub_mod = c[7:0];
end
else
sub_mod = c[7:0];
end
endfunction // function sub_mod
endmodule
数据RAM:
module data_ram(
WE,
WCLK,
RCLK,
ADDRW,
ADDRR,
DATAW,
DATAR
);
input WE,WCLK,RCLK;
input [7:0] ADDRW,ADDRR;
input [7:0] DATAW;
output [7:0] DATAR;
reg [7:0] DATAR;
reg [7:0] mem [241:0];
always @ (posedge WCLK)
begin
if (WE)
mem[ADDRW] <= DATAW;
end
always @ (posedge RCLK)
begin
DATAR <= mem[ADDRR];
end
endmodule
卷积器设计:
module conv(
CLK,
RESET,
EN,
DATA_IN,
COEF,
DATA_FIRST,
DATA_LAST,
SUM_OUT,
SOE,
CLKOUT
);
input CLK,RESET;
input EN;
input signed [7:0] DATA_IN;
input signed [15:0] COEF;
input DATA_FIRST;
input DATA_LAST;
output signed [15:0] SUM_OUT;
output SOE,CLKOUT;
wire signed [23:0] mulresult;
reg signed [7:0] data0;
reg signed [15:0] data1;
reg signed [23:0] muldata;
reg signed [23:0] sum;
reg dedfirst0,dedfirst1;
reg deden0,deden1;
reg dedlast0,dedlast1,dedlast2;
assign mulresult = data0 * data1;
assign SOE = dedlast2;
assign SUM_OUT = sum[23:8];
assign CLKOUT = ~CLK;
always @ (posedge CLK or negedge RESET)
begin
if(!RESET)
begin
data0 <= 0;
data1 <= 0;
muldata <= 0;
end
else
begin
data0 <= DATA_IN;
data1 <= COEF;
muldata <= mulresult;
end
end
always @ (posedge CLK or negedge RESET)
begin
if(!RESET)
begin
dedfirst0 <= 0;
dedfirst1 <= 0;
dedlast0 <= 0;
dedlast1 <= 0;
dedlast2 <= 0;
deden0 <= 0;
deden1 <= 0;
end
else
begin
dedfirst0 <= DATA_FIRST;
dedfirst1 <= dedfirst0;
dedlast0 <= DATA_LAST;
dedlast1 <= dedlast0;
dedlast2 <= dedlast1;
deden0 <= EN;
deden1 <= deden0;
end
end
always @ (posedge CLK or negedge RESET)
begin
if(!RESET)
begin
sum <= 0;
end
else
begin
if(deden1)
if(dedfirst1)
sum <= muldata;
else
sum <= sum + muldata;
end
end
endmodule
系数ROM,本设计的系数由于是偶对称的,所以只需保存一半即可:
module rom_coef(
CLK,
ADDRESS,
DOUT,
);
input CLK;
input [6 : 0] ADDRESS;
output [15 : 0] DOUT;
reg [15 : 0] DOUT;
always @ (posedge CLK)
begin
case (ADDRESS)
7'd 0 :DOUT <= 16'h 0;
………………………………
7'd 120 :DOUT <= 16'h 4531;
default : DOUT <= 0;
endcase
end
endmodule
文章评论(0条评论)
登录后参与讨论