タイムシェアリング多重シフト加算乗算器
4041 ワード
きほんアルゴリズム
シフト加算は日常的に使用される手算アルゴリズムであり、シフト加算の説明は以下の通りである.積の初期値を0 とする.乗数の最低位が0であると積は変わらず、そうでないと積算被乗数 となる.乗数の1番目のビットが0である場合、積は変わらず、そうでない場合、左に1ビットシフトされた被乗数 を加算. ... 乗数のn番目のビット(最上位)が0の場合、積は変わらない、そうでない場合、左にシフトn番目の乗数 が加算される.
RTLコード
インタフェース定義部は、パラメトリック設計を採用し、WIDTHは乗数/被乗数のビット幅、multiplier_validが高くなると入力が有効で計算が開始されます.product_validが引き上げられた場合は計算が完了し、現在の出力が有効であることを示します
シフト部は,入力がある場合に2つの入力の大きさを比較し,小さな数で反復数を制御し,時間消費を低減する.小さい乗数が0でなければ、大きい数を左にシフトし、小さい数を右にシフトする.
累加部は、より小さい乗数が最低位が0である場合、積を一定に保つ.そうしないと、現在の大乗数を累加し、小乗数が0である場合、演算が終了したことを示し、出力が有効に高くなる.
テスト
自動化テストを使用して、上位レベルのメソッドを使用して積を計算し、出力と比較して等しいかどうかを確認します.
シフト加算は日常的に使用される手算アルゴリズムであり、シフト加算の説明は以下の通りである.
RTLコード
module serial_shiftadder_multipcation # (
parameter WIDTH = 4
)(
input clk, // Clock
input rst_n, // Asynchronous reset active low
input multiplier_valid,
input [WIDTH - 1:0]multiplier1,
input [WIDTH - 1:0]multiplier2,
output reg product_valid,
output reg [2 * WIDTH - 1:0]product
);
インタフェース定義部は、パラメトリック設計を採用し、WIDTHは乗数/被乗数のビット幅、multiplier_validが高くなると入力が有効で計算が開始されます.product_validが引き上げられた場合は計算が完了し、現在の出力が有効であることを示します
/*****************buffer and shift*******************/
reg [WIDTH - 1:0]min_mult;
reg [2 * WIDTH - 1:0]max_mult;
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
{max_mult,min_mult} <= 'b0;
end else if(multiplier_valid == 1'b1) begin
if(multiplier1 > multiplier2) begin
max_mult <= '{multiplier1};
min_mult <= multiplier2;
end else begin
max_mult <= '{multiplier2};
min_mult <= multiplier1;
end
end else if(min_mult != 'b0) begin
max_mult <= max_mult << 1;
min_mult <= min_mult >> 1;
end else begin
max_mult <= max_mult;
min_mult <= min_mult;
end
end
シフト部は,入力がある場合に2つの入力の大きさを比較し,小さな数で反復数を制御し,時間消費を低減する.小さい乗数が0でなければ、大きい数を左にシフトし、小さい数を右にシフトする.
/******************adder********************/
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
{product_valid,product} <= 'b0;
end else if(min_mult[0] == 1'b1) begin
product <= product + max_mult;
product_valid <= 1'b0;
end else if(min_mult != 'b0) begin
product <= product;
product_valid <= 1'b0;
end else if(multiplier_valid == 1'b1) begin
product <= 'b0;
product_valid <= 1'b0;
end else begin
product <= product;
product_valid <= 1'b1;
end
end
endmodule
累加部は、より小さい乗数が最低位が0である場合、積を一定に保つ.そうしないと、現在の大乗数を累加し、小乗数が0である場合、演算が終了したことを示し、出力が有効に高くなる.
テスト
自動化テストを使用して、上位レベルのメソッドを使用して積を計算し、出力と比較して等しいかどうかを確認します.
module mult_tb (
);
parameter WIDTH = 4;
logic clk,rst_n;
logic multiplier_valid;
logic [WIDTH - 1:0]multiplier1;
logic [WIDTH - 1:0]multiplier2;
logic product_valid;
logic [2 * WIDTH - 1:0]product;
serial_shiftadder_multipcation # (
.WIDTH(WIDTH)
) dut (
.clk(clk), // Clock
.rst_n(rst_n), // Asynchronous reset active low
.multiplier_valid(multiplier_valid),
.multiplier1(multiplier1),
.multiplier2(multiplier2),
.product_valid(product_valid),
.product(product)
);
initial begin
clk = 1'b0;
forever begin
#50 clk = ~clk;
end
end
initial begin
rst_n = 1'b1;
#5 rst_n = 1'b0;
#10 rst_n = 1'b1;
end
initial begin
{multiplier_valid,multiplier1,multiplier2} = 'b0;
forever begin
@(negedge clk);
if(product_valid == 1'b1) begin
multiplier1 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
multiplier2 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
multiplier_valid = 1'b1;
end else begin
multiplier_valid = 1'b0;
end
end
end
logic [2 * WIDTH - 1:0]exp;
initial begin
forever begin
@(posedge product_valid);
exp = multiplier1 * multiplier2;
if(exp == product) begin
$display("successfully, mult1=%d mult2=%d product=%d",multiplier1,multiplier2,product);
end else begin
$display("failed,mult1=%d mult2=%d product=%d exp=%d",multiplier1,multiplier2,product,exp);
end
end
end
endmodule