1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

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