请设计一个输入8bits数据的开根运算器,条件:(1)输入不连续,两个输入数据至少间隔5个时钟周期,(2)消耗资源尽可能少,(3)输出结果保留整数 部分并完成四舍五入; module sqrt8dat( input clk, input rst_n, input [7:0] din, input din_vld, output wire [3:0] dout, output wire dout_vld ); 请将代码补充完整
时间: 2023-06-16 21:03:19 浏览: 300
根据条件,我们可以采用流水线的方式,将8bits数据输入分为两个阶段,每个阶段需要消耗一些资源,同时满足了输入不连续的条件。
第一阶段:将输入数据扩展为16bits并进行加法运算,得到一个8bits的中间结果。这个阶段需要用到一个16bits的加法器。
第二阶段:对中间结果进行开根运算,得到4bits的整数部分。这个阶段可以采用查表法,预先计算好所有可能的8bits数据的整数部分,并存储在一个ROM中。每个8bits数据对应一个4bits的整数部分,可以直接输出。这个阶段需要用到一个ROM。
最后,对整数部分进行四舍五入,得到最终的输出结果。这个过程可以用一个简单的比较器实现。
下面是完整的代码实现:
```verilog
module sqrt8dat(
input clk,
input rst_n,
input [7:0] din,
input din_vld,
output reg [3:0] dout,
output reg dout_vld
);
// 中间结果寄存器
reg [15:0] mid_res;
// 整数部分ROM
reg [3:0] int_part_rom [255:0];
// 比较器阈值
parameter [3:0] cmp_thr = 8'h8;
// ROM初始化
initial begin
for (int i = 0; i < 256; i = i + 1) begin
int_part_rom[i] = $clog2(i);
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
mid_res <= 0;
dout_vld <= 0;
dout <= 0;
end
else if (din_vld) begin
mid_res <= {8'b0, din} + mid_res;
end
else begin
mid_res <= mid_res;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
dout_vld <= 0;
dout <= 0;
end
else if (din_vld) begin
if ($unsigned(mid_res) < (16'h100)) begin
dout_vld <= 1;
dout <= int_part_rom[$unsigned(mid_res[15:8])];
if ((mid_res[7:0] >= cmp_thr) || ((mid_res[7:0] == cmp_thr-1) && (dout[0] == 1'b1))) begin
dout <= dout + 1;
end
end
else begin
dout_vld <= 0;
dout <= 0;
end
end
else begin
dout_vld <= 0;
dout <= 0;
end
end
endmodule
```
阅读全文