OpenCores
URL https://opencores.org/ocsvn/gng/gng/trunk

Subversion Repositories gng

[/] [gng/] [trunk/] [rtl/] [gng_interp.v] - Rev 7

Compare with Previous | Blame | View Log

//------------------------------------------------------------------------------
//
// gng_interp.v
//
// This file is part of the Gaussian Noise Generator IP Core
//
// Description
//     Polynomial interpolation.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2014, Guangxi Liu <guangxi.liu@opencores.org>
//
// This source file may be used and distributed without restriction provided
// that this copyright statement is not removed from the file and that any
// derivative work contains the original copyright notice and the associated
// disclaimer.
//
// This source file is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License,
// or (at your option) any later version.
//
// This source is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
// License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this source; if not, download it from
// http://www.opencores.org/lgpl.shtml
//
//------------------------------------------------------------------------------
 
 
`timescale 1 ns / 1 ps
 
 
module gng_interp (
    // System signals
    input clk,                    // system clock
    input rstn,                   // system synchronous reset, active low
 
    // Data interface
    input valid_in,               // input data valid
    input [63:0] data_in,         // input data
    output reg valid_out,         // output data valid
    output reg [15:0] data_out    // output data, s<16,11>
);
 
// Local variables
wire [5:0] num_lzd;
reg [5:0] num_lzd_r;
reg [14:0] mask;
reg [1:0] offset;
wire [7:0] addr;
wire [17:0] c0;    // u<18,14>
wire [17:0] c1;    // s<18,19>
wire [16:0] c2;    // u<17,23>
reg [14:0] x;      // u<15,15>
reg [14:0] x_r1, x_r2, x_r3, x_r4;   // u<15,15>
reg [17:0] c1_r1;    // s<18,19>
wire [37:0] sum1;    // s<38,38>
wire [17:0] sum1_new;    // s<18,18>
wire [33:0] mul1;    // s<34,33>
wire signed [13:0] mul1_new;    // s<14,14>
reg [17:0] c0_r1, c0_r2, c0_r3, c0_r4, c0_r5;   // u<18,14>
reg signed [18:0] sum2;    // s<19,14>
reg [14:0] sum2_rnd;    // u<15,11>
reg [8:0] sign_r;
reg [8:0] valid_in_r;
 
 
// Leading zero detector
gng_lzd u_gng_lzd (
    .data_in(data_in[63:3]),
    .data_out(num_lzd)
);
 
always @ (posedge clk) begin
    if (!rstn)
        num_lzd_r <= 6'd0;
    else
        num_lzd_r <= num_lzd;
end
 
 
// Get mask for value x
always @ (posedge clk) begin
    if (!rstn)
        mask <= 15'b111111111111111;
    else begin
        case (num_lzd_r)
            6'd61:   mask <= 15'b111111111111111;
            6'd60:   mask <= 15'b011111111111111;
            6'd59:   mask <= 15'b101111111111111;
            6'd58:   mask <= 15'b110111111111111;
            6'd57:   mask <= 15'b111011111111111;
            6'd56:   mask <= 15'b111101111111111;
            6'd55:   mask <= 15'b111110111111111;
            6'd54:   mask <= 15'b111111011111111;
            6'd53:   mask <= 15'b111111101111111;
            6'd52:   mask <= 15'b111111110111111;
            6'd51:   mask <= 15'b111111111011111;
            6'd50:   mask <= 15'b111111111101111;
            6'd49:   mask <= 15'b111111111110111;
            6'd48:   mask <= 15'b111111111111011;
            6'd47:   mask <= 15'b111111111111101;
            6'd46:   mask <= 15'b111111111111110;
            default: mask <= 15'b111111111111111;
        endcase
    end
end
 
 
// Generate table address and coefficients
always @ (posedge clk) begin
    if (!rstn)
        offset <= 2'd0;
    else
        offset <= {data_in[1], data_in[2]};
end
 
assign addr = {num_lzd_r, offset};
 
gng_coef u_gng_coef (
    .clk(clk),
    .addr(addr),
    .c0(c0),
    .c1(c1),
    .c2(c2)
);
 
 
// Data delay
always @ (posedge clk) begin
    if (!rstn)
        x <= 15'd0;
    else
        x <= {data_in[3], data_in[4], data_in[5], data_in[6], data_in[7],
              data_in[8], data_in[9], data_in[10], data_in[11], data_in[12],
              data_in[13], data_in[14], data_in[15], data_in[16], data_in[17]};
end
 
always @ (posedge clk) begin
    x_r1 <= x & mask;
    x_r2 <= x_r1;
    x_r3 <= x_r2;
    x_r4 <= x_r3;
end
 
always @ (posedge clk) begin
    c1_r1 <= c1;
end
 
always @ (posedge clk) begin
    c0_r1 <= c0;
    c0_r2 <= c0_r1;
    c0_r3 <= c0_r2;
    c0_r4 <= c0_r3;
    c0_r5 <= c0_r4;
end
 
always @ (posedge clk) begin
    sign_r <= {sign_r[7:0], data_in[0]};
end
 
always @ (posedge clk) begin
    if (!rstn)
        valid_in_r <= 9'd0;
    else
        valid_in_r <= {valid_in_r[7:0], valid_in};
end
 
 
// Polynomial interpolation of order 2
gng_smul_16_18_sadd_37 u_gng_smul_16_18_sadd_37 (
    .clk(clk),
    .a({1'b0, x_r1}),
    .b({1'b0, c2}),
    .c({c1_r1, 19'd0}),
    .p(sum1)
);
 
assign sum1_new = sum1[37:20];
 
gng_smul_16_18 u_gng_smul_16_18 (
    .clk(clk),
    .a({1'b0, x_r4}),
    .b(sum1_new),
    .p(mul1)
);
 
assign mul1_new = mul1[32:19];
 
always @ (posedge clk) begin
    sum2 <= $signed({1'b0, c0_r5}) + mul1_new;
end
 
always @ (posedge clk) begin
    sum2_rnd <= sum2[17:3] + sum2[2];
end
 
 
// Output data
always @ (posedge clk) begin
    if (!rstn)
        valid_out <= 1'b0;
    else
        valid_out <= valid_in_r[8];
end
 
always @ (posedge clk) begin
    if (!rstn)
        data_out <= 16'd0;
    else if (sign_r[8])
        data_out <= {1'b1, ~sum2_rnd} + 1'b1;
    else
        data_out <= {1'b0, sum2_rnd};
end
 
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.