1.数字加减法操作 、绝对值,乘数或除数为2^n乘除运算-归纳
2.二范数开根号码实战 out = (a*a b*b)^1/2 :JPL近似法
3.整数乘法代码实战 out = a*b :LUT 乘法器-通过搜索整数平方表来实现
1.数字加减法操作 、绝对值、被乘数或被除数为2^n乘除运算-归纳
以 DATA_WIDTH=8 以位有符号数为例。
:out = {a[DATA_WIDTH - 1], a} {b[DATA_WIDTH - 1], b};
:out = {a[DATA_WIDTH - 1], a} { ~b[DATA_WIDTH - 1], ~ b 1'b1};
:out = a[DATA_WIDTH - 1] ? (~a 1'b1) : a;
:out ={a[DATA_WIDTH - 1], a[DATA_WIDTH-(n 1):0], n'b0} ;//n'b0 N位宽的0数据不是有效语法,使用时需要常量数字
:out = {(n 1)'b({a[DATA_WIDTH - 1]), a[DATA_WIDTH-(n 1):0]} ; //(n 1)'b({a[DATA_WIDTH - 1]) 表示n 一位宽,每位都是a的符号位,数据。这是为了应对a的负数
2.二范数开根号码实战 out = (a*a b*b)^1/2 :JPL近似法(点击查看理论)
`timescale 1ns / 1ns module sqrt_x2_y2#(parameter DATA_WIDTH=8)( input wire sys_clk , input wire sys_rst_n, input wire [DATA_WIDTH-1:0] dataa , input wire [DATA_WIDTH-1:0] datab , output reg [DATA_WIDTH-1:0] ampout ); wire [DATA_WIDTH-1:0] dataa_abs ; wire [DATA_WIDTH-1:0] datab_abs ; wire a_than_b ; wire [DATA_WIDTH-1:0] dataabs_max,dataabs_min ; wire [DATA_WIDTH-1:0] absmin_3 ; // 求绝对值 assign dataa_abs = dataa[DATA_WIDTH-1] ? (~dataa 1'b1) : dataa ; assign datab_abs = datab[DATA_WIDTH-1] ? (~datab 1'b1) : datab; assign a_than_b = dataa_abs > datab_abs; //比较数据大小 assign {dataabs_max, dataabs_min} = dataa_abs > datab_abs ? {dataa_abs, datab_abs} : {datab_abs, dataa_abs} ; //计算 3倍min值 assign absmin_3 = {dataabs_min[DATA_WIDTH-1], dataabs_min} {dataabs_min[DATA_WIDTH-1],dataabs_min[DATA_WIDTH-2:0],1'b0} ; ///按条件接近公式 3min>data_abs_max always @(posedge sys_clk) begin if(!sys_rst_n) ampout <= #1 'd0; else if(absmin_3 > dataabs_max)// 7/8a 1/2 b ampout <= #1 {1'b0,dataabs_max} - {4'b0,dataabs_max[DATA_WIDTH-2:3]} {2'b0,dataabs_min[DATA_WIDTH-2:1]} ; else // a 1/8 b ampout <= #1 {1'b0,dataabs_max} {4'b0,dataabs_min[DATA_WIDTH-2:3]} ; end endmodule
`timescale 1ns / 1ns module tb_sqrt( ); parameter DATA_WIDTH = 8; reg sys_clk ; reg sys_rst_n; reg [DATA_WIDTH-1:0] dataa ; reg [DATA_WIDTH-1:0] datab ; wire [DATA_WIDTH-1:0] out ; initial begin sys_clk = 1'b0; sys_rst_n <= 1'b0; #40 sys_rst_n <= 1'b1; #100 #1000 $stop(); end always #10 sys_clk = ~sys_clk; always @(posedge sys_clk) begin if(!sys_rst_n) dataa <= 8'd1; else dataa <= 8'd3; end always @(posedgesys_clk) begin
if(!sys_rst_n)
datab <= 8'd1;
else
datab <= 8'd4;
end
sqrt_x2_y2
#( .DATA_WIDTH (DATA_WIDTH))
tb_sqrt_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n),
.dataa (dataa ) ,
.datab (datab ),
.ampout (out )
);
endmodule
3、整数乘法代码实战 out = a*b : LUT 乘法器-用查找整数平方表实现(点击查看理论)
这个例子不限于正负同号相乘,也可用于异号相乘。
`timescale 1ns / 1ns
module lut_mult
(
input clk,
input [7:0] in_1,
input [7:0] in_2,
output reg [15:0] out
);
reg [7:0] add;
reg [7:0] sub;
reg [15:0] out_data;
wire p_n;
wire[2:0] p_n_m;
// 计算输出符号
assign p_n = in_1[7]^in_2[7];
assign p_n_m = {p_n, p_n, p_n};
always @(*) begin
// 正数相加和相减
add = {in_1[7], in_1 } + { in_2[7], in_2};
sub = {in_1[7], in_1 }+ { ~in_2[7],~ in_2+1'b1};
// 将 a + b 的结果取正
add = add[7] ? (~add+1'b1) : add;
// 将 a - b 的结果取正
sub = sub[7] ? (~sub+1'b1) : sub;
// 平方相减除4
out_data = { 1'b0,get_256_pow(add) }+{1'b1, ~get_256_pow(sub) +1'b1};
out_data = {p_n_m, out_data[14:2]} ;
end
always @(posedge clk)
out <= #1 out_data;
// 查找表 LUT
/*
python 数据生成代码
f = open('log.txt','w')
for i in range(256):
f.write(" 17'd"+str(i)+" : get_256_pow = 19'd"+str(i*i)+" ;\n")
f.close()
*/
function [16:0] get_256_pow;
input [8:0] n;
begin
case(n)
9'd0 : get_256_pow = 17'd0 ;
9'd1 : get_256_pow = 17'd1 ;
9'd2 : get_256_pow = 17'd4 ;
9'd3 : get_256_pow = 17'd9 ;
9'd4 : get_256_pow = 17'd16 ;
9'd5 : get_256_pow = 17'd25 ;
9'd6 : get_256_pow = 17'd36 ;
9'd7 : get_256_pow = 17'd49 ;
9'd8 : get_256_pow = 17'd64 ;
9'd9 : get_256_pow = 17'd81 ;
9'd10 : get_256_pow = 17'd100 ;
9'd11 : get_256_pow = 17'd121 ;
9'd12 : get_256_pow = 17'd144 ;
9'd13 : get_256_pow = 17'd169 ;
9'd14 : get_256_pow = 17'd196 ;
9'd15 : get_256_pow = 17'd225 ;
9'd16 : get_256_pow = 17'd256 ;
9'd17 : get_256_pow = 17'd289 ;
9'd18 : get_256_pow = 17'd324 ;
9'd19 : get_256_pow = 17'd361 ;
9'd20 : get_256_pow = 17'd400 ;
9'd21 : get_256_pow = 17'd441 ;
9'd22 : get_256_pow = 17'd484 ;
9'd23 : get_256_pow = 17'd529 ;
9'd24 : get_256_pow = 17'd576 ;
9'd25 : get_256_pow = 17'd625 ;
9'd26 : get_256_pow = 17'd676 ;
9'd27 : get_256_pow = 17'd729 ;
9'd28 : get_256_pow = 17'd784 ;
9'd29 : get_256_pow = 17'd841 ;
9'd30 : get_256_pow = 17'd900 ;
9'd31 : get_256_pow = 17'd961 ;
9'd32 : get_256_pow = 17'd1024 ;
9'd33 : get_256_pow = 17'd1089 ;
9'd34 : get_256_pow = 17'd1156 ;
9'd35 : get_256_pow = 17'd1225 ;
9'd36 : get_256_pow = 17'd1296 ;
9'd37 : get_256_pow = 17'd1369 ;
9'd38 : get_256_pow = 17'd1444 ;
9'd39 : get_256_pow = 17'd1521 ;
9'd40 : get_256_pow = 17'd1600 ;
9'd41 : get_256_pow = 17'd1681 ;
9'd42 : get_256_pow = 17'd1764 ;
9'd43 : get_256_pow = 17'd1849 ;
9'd44 : get_256_pow = 17'd1936 ;
9'd45 : get_256_pow = 17'd2025 ;
9'd46 : get_256_pow = 17'd2116 ;
9'd47 : get_256_pow = 17'd2209 ;
9'd48 : get_256_pow = 17'd2304 ;
9'd49 : get_256_pow = 17'd2401 ;
9'd50 : get_256_pow = 17'd2500 ;
9'd51 : get_256_pow = 17'd2601 ;
9'd52 : get_256_pow = 17'd2704 ;
9'd53 : get_256_pow = 17'd2809 ;
9'd54 : get_256_pow = 17'd2916 ;
9'd55 : get_256_pow = 17'd3025 ;
9'd56 : get_256_pow = 17'd3136 ;
9'd57 : get_256_pow = 17'd3249 ;
9'd58 : get_256_pow = 17'd3364 ;
9'd59 : get_256_pow = 17'd3481 ;
9'd60 : get_256_pow = 17'd3600 ;
9'd61 : get_256_pow = 17'd3721 ;
9'd62 : get_256_pow = 17'd3844 ;
9'd63 : get_256_pow = 17'd3969 ;
9'd64 : get_256_pow = 17'd4096 ;
9'd65 : get_256_pow = 17'd4225 ;
9'd66 : get_256_pow = 17'd4356 ;
9'd67 : get_256_pow = 17'd4489 ;
9'd68 : get_256_pow = 17'd4624 ;
9'd69 : get_256_pow = 17'd4761 ;
9'd70 : get_256_pow = 17'd4900 ;
9'd71 : get_256_pow = 17'd5041 ;
9'd72 : get_256_pow = 17'd5184 ;
9'd73 : get_256_pow = 17'd5329 ;
9'd74 : get_256_pow = 17'd5476 ;
9'd75 : get_256_pow = 17'd5625 ;
9'd76 : get_256_pow = 17'd5776 ;
9'd77 : get_256_pow = 17'd5929 ;
9'd78 : get_256_pow = 17'd6084 ;
9'd79 : get_256_pow = 17'd6241 ;
9'd80 : get_256_pow = 17'd6400 ;
9'd81 : get_256_pow = 17'd6561 ;
9'd82 : get_256_pow = 17'd6724 ;
9'd83 : get_256_pow = 17'd6889 ;
9'd84 : get_256_pow = 17'd7056 ;
9'd85 : get_256_pow = 17'd7225 ;
9'd86 : get_256_pow = 17'd7396 ;
9'd87 : get_256_pow = 17'd7569 ;
9'd88 : get_256_pow = 17'd7744 ;
9'd89 : get_256_pow = 17'd7921 ;
9'd90 : get_256_pow = 17'd8100 ;
9'd91 : get_256_pow = 17'd8281 ;
9'd92 : get_256_pow = 17'd8464 ;
9'd93 : get_256_pow = 17'd8649 ;
9'd94 : get_256_pow = 17'd8836 ;
9'd95 : get_256_pow = 17'd9025 ;
9'd96 : get_256_pow = 17'd9216 ;
9'd97 : get_256_pow = 17'd9409 ;
9'd98 : get_256_pow = 17'd9604 ;
9'd99 : get_256_pow = 17'd9801 ;
9'd100 : get_256_pow = 17'd10000 ;
9'd101 : get_256_pow = 17'd10201 ;
9'd102 : get_256_pow = 17'd10404 ;
9'd103 : get_256_pow = 17'd10609 ;
9'd104 : get_256_pow = 17'd10816 ;
9'd105 : get_256_pow = 17'd11025 ;
9'd106 : get_256_pow = 17'd11236 ;
9'd107 : get_256_pow = 17'd11449 ;
9'd108 : get_256_pow = 17'd11664 ;
9'd109 : get_256_pow = 17'd11881 ;
9'd110 : get_256_pow = 17'd12100 ;
9'd111 : get_256_pow = 17'd12321 ;
9'd112 : get_256_pow = 17'd12544 ;
9'd113 : get_256_pow = 17'd12769 ;
9'd114 : get_256_pow = 17'd12996 ;
9'd115 : get_256_pow = 17'd13225 ;
9'd116 : get_256_pow = 17'd13456 ;
9'd117 : get_256_pow = 17'd13689 ;
9'd118 : get_256_pow = 17'd13924 ;
9'd119 : get_256_pow = 17'd14161 ;
9'd120 : get_256_pow = 17'd14400 ;
9'd121 : get_256_pow = 17'd14641 ;
9'd122 : get_256_pow = 17'd14884 ;
9'd123 : get_256_pow = 17'd15129 ;
9'd124 : get_256_pow = 17'd15376 ;
9'd125 : get_256_pow = 17'd15625 ;
9'd126 : get_256_pow = 17'd15876 ;
9'd127 : get_256_pow = 17'd16129 ;
9'd128 : get_256_pow = 17'd16384 ;
9'd129 : get_256_pow = 17'd16641 ;
9'd130 : get_256_pow = 17'd16900 ;
9'd131 : get_256_pow = 17'd17161 ;
9'd132 : get_256_pow = 17'd17424 ;
9'd133 : get_256_pow = 17'd17689 ;
9'd134 : get_256_pow = 17'd17956 ;
9'd135 : get_256_pow = 17'd18225 ;
9'd136 : get_256_pow = 17'd18496 ;
9'd137 : get_256_pow = 17'd18769 ;
9'd138 : get_256_pow = 17'd19044 ;
9'd139 : get_256_pow = 17'd19321 ;
9'd140 : get_256_pow = 17'd19600 ;
9'd141 : get_256_pow = 17'd19881 ;
9'd142 : get_256_pow = 17'd20164 ;
9'd143 : get_256_pow = 17'd20449 ;
9'd144 : get_256_pow = 17'd20736 ;
9'd145 : get_256_pow = 17'd21025 ;
9'd146 : get_256_pow = 17'd21316 ;
9'd147 : get_256_pow = 17'd21609 ;
9'd148 : get_256_pow = 17'd21904 ;
9'd149 : get_256_pow = 17'd22201 ;
9'd150 : get_256_pow = 17'd22500 ;
9'd151 : get_256_pow = 17'd22801 ;
9'd152 : get_256_pow = 17'd23104 ;
9'd153 : get_256_pow = 17'd23409 ;
9'd154 : get_256_pow = 17'd23716 ;
9'd155 : get_256_pow = 17'd24025 ;
9'd156 : get_256_pow = 17'd24336 ;
9'd157 : get_256_pow = 17'd24649 ;
9'd158 : get_256_pow = 17'd24964 ;
9'd159 : get_256_pow = 17'd25281 ;
9'd160 : get_256_pow = 17'd25600 ;
9'd161 : get_256_pow = 17'd25921 ;
9'd162 : get_256_pow = 17'd26244 ;
9'd163 : get_256_pow = 17'd26569 ;
9'd164 : get_256_pow = 17'd26896 ;
9'd165 : get_256_pow = 17'd27225 ;
9'd166 : get_256_pow = 17'd27556 ;
9'd167 : get_256_pow = 17'd27889 ;
9'd168 : get_256_pow = 17'd28224 ;
9'd169 : get_256_pow = 17'd28561 ;
9'd170 : get_256_pow = 17'd28900 ;
9'd171 : get_256_pow = 17'd29241 ;
9'd172 : get_256_pow = 17'd29584 ;
9'd173 : get_256_pow = 17'd29929 ;
9'd174 : get_256_pow = 17'd30276 ;
9'd175 : get_256_pow = 17'd30625 ;
9'd176 : get_256_pow = 17'd30976 ;
9'd177 : get_256_pow = 17'd31329 ;
9'd178 : get_256_pow = 17'd31684 ;
9'd179 : get_256_pow = 17'd32041 ;
9'd180 : get_256_pow = 17'd32400 ;
9'd181 : get_256_pow = 17'd32761 ;
9'd182 : get_256_pow = 17'd33124 ;
9'd183 : get_256_pow = 17'd33489 ;
9'd184 : get_256_pow = 17'd33856 ;
9'd185 : get_256_pow = 17'd34225 ;
9'd186 : get_256_pow = 17'd34596 ;
9'd187 : get_256_pow = 17'd34969 ;
9'd188 : get_256_pow = 17'd35344 ;
9'd189 : get_256_pow = 17'd35721 ;
9'd190 : get_256_pow = 17'd36100 ;
9'd191 : get_256_pow = 17'd36481 ;
9'd192 : get_256_pow = 17'd36864 ;
9'd193 : get_256_pow = 17'd37249 ;
9'd194 : get_256_pow = 17'd37636 ;
9'd195 : get_256_pow = 17'd38025 ;
9'd196 : get_256_pow = 17'd38416 ;
9'd197 : get_256_pow = 17'd38809 ;
9'd198 : get_256_pow = 17'd39204 ;
9'd199 : get_256_pow = 17'd39601 ;
9'd200 : get_256_pow = 17'd40000 ;
9'd201 : get_256_pow = 17'd40401 ;
9'd202 : get_256_pow = 17'd40804 ;
9'd203 : get_256_pow = 17'd41209 ;
9'd204 : get_256_pow = 17'd41616 ;
9'd205 : get_256_pow = 17'd42025 ;
9'd206 : get_256_pow = 17'd42436 ;
9'd207 : get_256_pow = 17'd42849 ;
9'd208 : get_256_pow = 17'd43264 ;
9'd209 : get_256_pow = 17'd43681 ;
9'd210 : get_256_pow = 17'd44100 ;
9'd211 : get_256_pow = 17'd44521 ;
9'd212 : get_256_pow = 17'd44944 ;
9'd213 : get_256_pow = 17'd45369 ;
9'd214 : get_256_pow = 17'd45796 ;
9'd215 : get_256_pow = 17'd46225 ;
9'd216 : get_256_pow = 17'd46656 ;
9'd217 : get_256_pow = 17'd47089 ;
9'd218 : get_256_pow = 17'd47524 ;
9'd219 : get_256_pow = 17'd47961 ;
9'd220 : get_256_pow = 17'd48400 ;
9'd221 : get_256_pow = 17'd48841 ;
9'd222 : get_256_pow = 17'd49284 ;
9'd223 : get_256_pow = 17'd49729 ;
9'd224 : get_256_pow = 17'd50176 ;
9'd225 : get_256_pow = 17'd50625 ;
9'd226 : get_256_pow = 17'd51076 ;
9'd227 : get_256_pow = 17'd51529 ;
9'd228 : get_256_pow = 17'd51984 ;
9'd229 : get_256_pow = 17'd52441 ;
9'd230 : get_256_pow = 17'd52900 ;
9'd231 : get_256_pow = 17'd53361 ;
9'd232 : get_256_pow = 17'd53824 ;
9'd233 : get_256_pow = 17'd54289 ;
9'd234 : get_256_pow = 17'd54756 ;
9'd235 : get_256_pow = 17'd55225 ;
9'd236 : get_256_pow = 17'd55696 ;
9'd237 : get_256_pow = 17'd56169 ;
9'd238 : get_256_pow = 17'd56644 ;
9'd239 : get_256_pow = 17'd57121 ;
9'd240 : get_256_pow = 17'd57600 ;
9'd241 : get_256_pow = 17'd58081 ;
9'd242 : get_256_pow = 17'd58564 ;
9'd243 : get_256_pow = 17'd59049 ;
9'd244 : get_256_pow = 17'd59536 ;
9'd245 : get_256_pow = 17'd60025 ;
9'd246 : get_256_pow = 17'd60516 ;
9'd247 : get_256_pow = 17'd61009 ;
9'd248 : get_256_pow = 17'd61504 ;
9'd249 : get_256_pow = 17'd62001 ;
9'd250 : get_256_pow = 17'd62500 ;
9'd251 : get_256_pow = 17'd63001 ;
9'd252 : get_256_pow = 17'd63504 ;
9'd253 : get_256_pow = 17'd64009 ;
9'd254 : get_256_pow = 17'd64516 ;
9'd255 : get_256_pow = 17'd65025 ;
default: get_256_pow = 17'd1 ;
endcase
end
endfunction
endmodule
`timescale 1ns / 1ns
module tb_my_mux( );
reg clk;
reg [7:0] in_1;
reg [7:0] in_2;
reg start;
wire [15:0] out;
initial begin
start = 1'b0;
clk = 1'b0;
in_1 =8'd0;
in_2 =8'd0;
#40
start <= 1'b1;
#600
start <= 1'b0;
#400
$stop();
end
always #10 clk = ~clk;
always @(posedge clk) begin
if(start)
in_1 <=8'd0-8'd2;
else
in_1 <=8'd1;
end
always @(posedge clk) begin
if(start)
in_2 <=8'd4;
else
in_2 <=8'd1;
end
lut_mult my_mux
(
. clk (clk),
.in_1 (in_1),
.in_2 (in_2),
.out (out)
);
endmodule