思路:
先载入数据到4个寄存器,再逐个累加,累加后载入数据到除法器中进行除法运算。
1、计算平均数模块
`timescale 1ns/1ps
module Ave(Clk,Rst_n,s,Data,ER,w0,w1,Done,R,Q);
parameter n = 8;
input Clk,Rst_n,s,ER,w0,w1;
input [n-1:0] Data;
output [n-1:0] R,Q;
output Done;
reg [7:0] data0,data1,data2,data3;
reg y0,y1,y2,y3;
wire LC ,EC,Ssel,ES;
reg [n-1:0] sum;
wire S_d,LA,EB;
wire div_done;
reg [1:0] cnt;
parameter S1=3'b000,S2=3'b001,S3=3'b010,S4=3'b011,S5=3'b100;
reg [2:0] state,next_state;
always@(*) begin
if(ER)
case({w1,w0})
2'b00:{y0,y1,y2,y3} = 4'b1000;
2'b01:{y0,y1,y2,y3} = 4'b0100;
2'b10:{y0,y1,y2,y3} = 4'b0010;
2'b11:{y0,y1,y2,y3} = 4'b0001;
default:{y0,y1,y2,y3} = 4'b0000;
endcase
else
{y0,y1,y2,y3} = 4'b0000;
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
data0 <= 0;
else if(y0)
data0 <= Data;
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
data1 <= 0;
else if(y1)
data1 <= Data;
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
data2 <= 0;
else if(y2)
data2 <= Data;
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
data3 <= 0;
else if(y3)
data3 <= Data;
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
cnt <= 2'd3;
else if(LC)
cnt <= 2'd3;
else if (EC)
cnt <= cnt - 1'b1;
end
always@(posedge Clk or negedge Rst_n) begin
if(~Rst_n)
sum <= 0;
else if(ES)
if(Ssel)
case(cnt)
2'b00:sum <= sum + data0;
2'b01:sum <= sum + data1;
2'b10:sum <= sum + data2;
2'b11:sum <= sum + data3;
default:;
endcase
else
sum <=0;
else
sum <= 0;
end
always@(*) begin
case(state)
S1:
if(s) next_state =S2;
S2:
if(~|cnt) next_state =S3;
S3:
next_state = S4;
S4:
next_state = div_done?S5:S4;
S5:
next_state=s?S5:S1;
default: next_state = S1;
endcase
end
always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n)
state <= S1;
else
state <= next_state;
end
Div div0(.Clk(Clk),.Rst_n(Rst_n),.s(S_d),.DataA(sum),.DataB(8'd4),.LA(LA),.EB(EB),.R(R),.Q(Q),.Done(div_done));
assign Done = state==S5;
assign Ssel = state==S2;
assign ES = state==S2;
assign LC = state==S1&s;
assign EC = state==S2;
assign S_d = state==S4;
assign LA = state==S3;
assign EB = state==S3;
endmodule
2、测试代码
`timescale 1ns/1ps
`define clk_period 20
module tb_Div();
reg clk,rst_n,s,la;
reg [7:0] a;
reg [1:0] c;
//#wire [15:0] p;
wire done;
wire [7:0] q,r;
Ave adiv0(.Clk(clk),.Rst_n(rst_n),.Data(a),.ER(la),.s(s),.Q(q),.R(r),.Done(done),.w1(c[1]),.w0(c[0]));
initial clk = 1'b1;
always #(`clk_period /2) clk = ~clk;
initial begin
rst_n = 0 ; la=0;
s = 0 ;
a = 8'd0;
# (5*`clk_period/2) rst_n =1;
# 20;a=8'd20;la=1;c=2'b00;
# 20;a=8'd21;c=2'b01;
# 20;a=8'd22;c=2'b10;
# 20;a=8'd25;c=2'b11;
# 20 ;la=0;s=1;
#(20*`clk_period);
s=0;
#200;
# 20; a=8'd00;la=1;c=2'b00;
# 20; a=8'd01;c=2'b01;
# 20; a=8'd22;c=2'b10;
# 20; a=8'd25;c=2'b11;
# 20 ;la=0;s=1;
#(20*`clk_period);
s=0;
# 20;a=8'd00;la=1;c=2'b00;
# 20;a=8'd01;c=2'b01;
# 20;a=8'd02;c=2'b10;
# 20;a=8'd01;c=2'b11;
# 20 ;la=0;s=1;
#(20*`clk_period);
s=0;
# 20;a=8'd20;la=1;c=2'b00;
# 20;a=8'd121;c=2'b01;
# 20;a=8'd22;c=2'b10;
# 20;a=8'd26;c=2'b11;
# 20 ;la=0;s=1;
#(20*`clk_period);
s=0;
end
initial
begin
$fsdbDumpfile("avediv.fsdb");
$fsdbDumpvars;
$fsdbDumpon;
end
initial #5000 $finish;
endmodule