原创 【博客大赛】直接型FIR的FPGA设计(四)

2012-4-22 20:36 1462 19 19 分类: FPGA/CPLD

(四)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条评论)

登录后参与讨论
我要评论
0
19
关闭 站长推荐上一条 /2 下一条