Added mul tb and fixed
This commit is contained in:
@@ -17,11 +17,11 @@ module mul_const_shiftadd#(
|
||||
input wire signed [W-1:0] x,
|
||||
output wire signed [2*W-1:0] y
|
||||
);
|
||||
// Absolute value and sign of C
|
||||
localparam integer C_NEG = (C < 0) ? 1 : 0;
|
||||
localparam integer C_ABS = (C < 0) ? -C : C;
|
||||
// Sign and magnitude of constant
|
||||
localparam integer C_NEG = (C < 0) ? 1 : 0;
|
||||
localparam integer C_ABS = (C < 0) ? -C : C;
|
||||
|
||||
// Find MSB index of C_ABS to size the network
|
||||
// MSB index of |C| (0-based). Keeps network minimal.
|
||||
function integer msb_index;
|
||||
input integer v;
|
||||
integer i;
|
||||
@@ -31,19 +31,26 @@ module mul_const_shiftadd#(
|
||||
if (v >> i) msb_index = i;
|
||||
end
|
||||
endfunction
|
||||
|
||||
localparam integer I_MAX = (C_ABS == 0) ? 0 : msb_index(C_ABS);
|
||||
|
||||
// Partial products
|
||||
wire signed [W+I_MAX:0] part [0:I_MAX];
|
||||
// Width big enough for the largest partial product: W bits shifted by I_MAX
|
||||
localparam integer PPW = W + I_MAX + 1;
|
||||
|
||||
// Pre-extend x to PPW so shifts don’t truncate high/sign bits
|
||||
wire signed [PPW-1:0] x_ext = {{(PPW-W){x[W-1]}}, x};
|
||||
|
||||
// Partial products (only where C’s bit is 1)
|
||||
wire signed [PPW-1:0] part [0:I_MAX];
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i <= I_MAX; i = i + 1) begin : GEN_PARTS
|
||||
assign part[i] = (C_ABS[i]) ? ($signed(x) <<< i) : { (W+I_MAX+1){1'b0} };
|
||||
assign part[i] = C_ABS[i] ? (x_ext <<< i) : {PPW{1'b0}};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Adder chain (simple; replace with tree if you want higher performance)
|
||||
wire signed [W+I_MAX:0] sum [0:I_MAX];
|
||||
// Adder chain (you can replace with a balanced tree for speed)
|
||||
wire signed [PPW-1:0] sum [0:I_MAX];
|
||||
generate
|
||||
if (I_MAX == 0) begin
|
||||
assign sum[0] = part[0];
|
||||
@@ -56,10 +63,9 @@ module mul_const_shiftadd#(
|
||||
endgenerate
|
||||
|
||||
// Apply sign of C
|
||||
wire signed [W+I_MAX:0] mag = (I_MAX==0) ? part[0] : sum[I_MAX];
|
||||
wire signed [W+I_MAX:0] prod = C_NEG ? -mag : mag;
|
||||
|
||||
// Stretch to fixed y width (truncate/extend as you wish outside)
|
||||
assign y = prod;
|
||||
wire signed [PPW-1:0] mag = (I_MAX == 0) ? part[0] : sum[I_MAX];
|
||||
wire signed [PPW-1:0] prod = C_NEG ? -mag : mag;
|
||||
|
||||
// Stretch/extend to 2W result width
|
||||
assign y = {{((2*W)-PPW){prod[PPW-1]}}, prod};
|
||||
endmodule
|
||||
@@ -12,7 +12,7 @@
|
||||
// -- clk : input clock
|
||||
// -- resetn : reset signal
|
||||
// -- sd_sample : 1 bit sample output from sd sampler
|
||||
// -- sample_q15 : output samples in q1.15
|
||||
// -- sample_q15 : output samples in q.15
|
||||
// =============================================================================
|
||||
module sigmadelta_rcmodel_q15 #(
|
||||
parameter integer alpha_q15 = 16'sh0b00
|
||||
@@ -25,9 +25,10 @@ module sigmadelta_rcmodel_q15 #(
|
||||
reg signed [15:0] y_q15;
|
||||
wire signed [15:0] sd_q15 = sd_sample ? 16'sh7fff : 16'sh0000;
|
||||
wire signed [15:0] e_q15 = sd_q15 - y_q15;
|
||||
// wire signed [31:0] prod_q30 = $signed(e_q15) * $signed(alpha_q15);
|
||||
wire signed [31:0] prod_q30;
|
||||
// Use shift-add algorithm for multiplication
|
||||
mul_const_shiftadd #(.C(alpha_q15)) alpha_times_e (e_q15, prod_q30);
|
||||
mul_const_shiftadd #(.C($signed(alpha_q15))) alpha_times_e ($signed(e_q15), prod_q30);
|
||||
wire signed [15:0] y_next_q15 = y_q15 + (prod_q30>>>15);
|
||||
|
||||
// clamp to [0, 0x7FFF] (keeps signal view tidy)
|
||||
|
||||
Reference in New Issue
Block a user