mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
162 lines
4.5 KiB
Verilog
162 lines
4.5 KiB
Verilog
// Copyright 2007 Altera Corporation. All rights reserved.
|
|
// Altera products are protected under numerous U.S. and foreign patents,
|
|
// maskwork rights, copyrights and other intellectual property laws.
|
|
//
|
|
// This reference design file, and your use thereof, is subject to and governed
|
|
// by the terms and conditions of the applicable Altera Reference Design
|
|
// License Agreement (either as signed by you or found at www.altera.com). By
|
|
// using this reference design file, you indicate your acceptance of such terms
|
|
// and conditions between you and Altera Corporation. In the event that you do
|
|
// not agree with such terms and conditions, you may not use the reference
|
|
// design file and please promptly destroy any copies you have made.
|
|
//
|
|
// This reference design file is being provided on an "as-is" basis and as an
|
|
// accommodation and therefore all warranties, representations or guarantees of
|
|
// any kind (whether express, implied or statutory) including, without
|
|
// limitation, warranties of merchantability, non-infringement, or fitness for
|
|
// a particular purpose, are specifically disclaimed. By making this reference
|
|
// design file available, Altera expressly does not recommend, suggest or
|
|
// require that this reference design file be used in combination with any
|
|
// other product not provided by Altera.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// baeckler -01-02-2007
|
|
module lc_mult_signed (clk,a,b,o);
|
|
|
|
parameter WIDTH_A = 16;
|
|
parameter WIDTH_B = 13;
|
|
parameter WIDTH_O = WIDTH_A + WIDTH_B;
|
|
parameter REGISTER_LAYERS = 1;
|
|
parameter REGISTER_MIDPOINTS = 1;
|
|
|
|
/////////////////////////////////////
|
|
// these are just for sanity - to
|
|
// display the actual latency in
|
|
// simulation.
|
|
/////////////////////////////////////
|
|
function integer layer_latency;
|
|
input integer words;
|
|
begin
|
|
layer_latency = 2;
|
|
while (words > 1) begin
|
|
words = (words/2) + (words - (2*(words/2)));
|
|
layer_latency = layer_latency + 1;
|
|
end
|
|
end
|
|
endfunction
|
|
|
|
function integer midpoint_latency;
|
|
input integer words;
|
|
begin
|
|
midpoint_latency = 0;
|
|
while (words > 1) begin
|
|
words = (words/2) + (words - (2*(words/2)));
|
|
midpoint_latency = midpoint_latency + 1;
|
|
end
|
|
end
|
|
endfunction
|
|
|
|
input clk;
|
|
input [WIDTH_A-1:0] a;
|
|
input [WIDTH_B-1:0] b;
|
|
output [WIDTH_O-1:0] o;
|
|
|
|
wire b_negative = b[WIDTH_B-1];
|
|
wire [WIDTH_O-1:0] o_wire;
|
|
reg [WIDTH_O-1:0] o;
|
|
|
|
genvar i;
|
|
wire [WIDTH_B * WIDTH_A - 1:0] partials;
|
|
|
|
// report the latency in simulation
|
|
generate
|
|
if (REGISTER_LAYERS) begin
|
|
initial begin
|
|
$display ("lc_mult_signed layer latency for WIDTH_B=%d is %d",
|
|
WIDTH_B,layer_latency(WIDTH_B));
|
|
end
|
|
end
|
|
if (REGISTER_MIDPOINTS) begin
|
|
initial begin
|
|
$display ("lc_mult_signed midpoint latency for WIDTH_B=%d is %d",
|
|
WIDTH_B,midpoint_latency(WIDTH_B));
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
/////////////////////////////////////
|
|
// Construct the partial products
|
|
/////////////////////////////////////
|
|
|
|
// for all but the last word do simple AND gates
|
|
generate
|
|
for (i=0; i<(WIDTH_B-1); i=i+1)
|
|
begin : ps
|
|
assign partials[i*WIDTH_A+WIDTH_A-1:i*WIDTH_A] = a & {WIDTH_A{b[i]}};
|
|
end
|
|
endgenerate
|
|
|
|
// for the last word and with !A
|
|
// this is analagous to B and (B xor A)
|
|
assign partials[WIDTH_B*WIDTH_A-1:WIDTH_B*WIDTH_A-WIDTH_A] = ~a & {WIDTH_A{b[WIDTH_B-1]}};
|
|
|
|
reg [WIDTH_B * WIDTH_A - 1:0] partials_r;
|
|
reg b_negative_r;
|
|
generate
|
|
if (REGISTER_LAYERS) begin
|
|
always @(posedge clk) begin
|
|
partials_r <= partials;
|
|
b_negative_r <= b_negative;
|
|
end
|
|
end
|
|
else begin
|
|
always @(*) begin
|
|
partials_r = partials;
|
|
b_negative_r <= b_negative;
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
/////////////////////////////////////
|
|
// Sum the partial products
|
|
/////////////////////////////////////
|
|
wire [WIDTH_O-1:0] sum;
|
|
wire b_negative_final;
|
|
adder_tree at (.clk(clk),
|
|
.in_words(partials_r),
|
|
.extra_bit_in(b_negative_r),
|
|
.extra_bit_out(b_negative_final),
|
|
.out(sum));
|
|
defparam at .NUM_IN_WORDS = WIDTH_B;
|
|
defparam at .BITS_PER_IN_WORD = WIDTH_A;
|
|
defparam at .OUT_BITS = WIDTH_O;
|
|
defparam at .SIGN_EXT = 1;
|
|
defparam at .REGISTER_OUTPUT = REGISTER_LAYERS;
|
|
defparam at .REGISTER_MIDDLE = REGISTER_MIDPOINTS;
|
|
defparam at .SHIFT_DIST = 1;
|
|
defparam at .EXTRA_BIT_USED = 1;
|
|
|
|
/////////////////////////////////////
|
|
// final signed correction
|
|
/////////////////////////////////////
|
|
assign o_wire = sum + (b_negative_final << (WIDTH_B-1));
|
|
|
|
/////////////////////////////////////
|
|
// optional output registers
|
|
/////////////////////////////////////
|
|
generate
|
|
if (REGISTER_LAYERS) begin
|
|
always @(posedge clk) begin
|
|
o <= o_wire;
|
|
end
|
|
end
|
|
else begin
|
|
always @(*) begin
|
|
o = o_wire;
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|
|
|