Adv. Verilog Parametric Code Snippets

Who needs those fangled Scala-HDLs, when they can use generate in Verilog2001.

— Sun Tzu

TOC / Jul.22.2021

  1. Parallel Combinational Maxima Function
  2. SAR Controller

  1. Parallel Combinational Maxima Function
// max_parallel
//
// Generates a parallel combinational maximum value function 
// Synthesizable
module max_parallel #(
    parameter NARGLOG = 5,
    parameter ISIZE   = 32
)(
    input [ISIZE-1:0]           A [2**NARGLOG-1:0],
    output reg [NARGLOG-1:0]    maxn,
    output reg [ISIZE-1:0]      maxval
);
    wire [ISIZE-1:0]   t  [2**(NARGLOG+1)-1:0];
    wire [NARGLOG-1:0] tn [2**(NARGLOG+1)-1:0];
    assign t[2**(NARGLOG+1)-1:2**NARGLOG] = A;
    assign maxval = t [1];
    assign maxn   = tn[1];
    // t[0] and tn[0] are unused.
    genvar gi, gj;
    generate
    for(gi=0;gi<2**NARGLOG;gi=gi+1) begin : gen_assign_cell_id
        assign tn[2**NARGLOG-1+gi] = gi;
    end
    
    for(gi=0;gi<NARGLOG;gi=gi+1) begin : gen_cell_layer
        for(gj=0;gj<2**gi;gj=gj+1) begin : gen_cells
            integer bias = 2**gi;
            max2 umax(
                .a0     (t [bias+gj+bias]),
                .maxn0  (tn[bias+gj+bias]),
                .a1     (t [bias+gj+bias*2]),
                .maxn1  (tn[bias+gj+bias*2]),
                .maxval (t [2**gi+gj]),         // VCS doesn't like this
                .maxn   (tn[2**gi+gj])
            );
        end
    end
    endgenerate
endmodule

// max2
//
//
module max2 #(
    parameter NLOGMAX = 5,
    parameter ISIZE   = 32
)(
    input  [ISIZE-1:0]      a0,
    input  [NLOGMAX-1:0]    maxn0,
    input  [ISIZE-1:0]      a1,
    input  [NLOGMAX-1:0]    maxn1,
    output [ISIZE-1:0]      maxval,
    output [NLOGMAX-1:0]    maxn
);
    wire   maxsel = (a1>a0);
    assign maxsel ? maxn1 : maxn0;
    assign maxval ? a1    : a0;
endmodule

2.SAR Controller

module sarcell #(parameter init = 0)(
    input       start_n,
    input       clk,
    input       a,
    input       shift,
    input       en_n,
    output reg  k
    );
    reg d;
    always @ * begin
        casex ({en_n, k})
            2'b1x:      d = k;
            2'b01:      d = a;
            2'b00:      d = shift;
            default:    d = 1'bx;
        endcase
    end
    always @ (posedge clk or negedge start_n) begin
        if(!start_n)    k <= init;
        else            k <= d;
    end

endmodule // sarcell

module sar_test #(parameter DEPTH = 8)(
    input               start_n,
    input               comp,
    input               clk_sar,
    input               locked,
    output [DEPTH:0]    bits,
    output              stop
    );

    wire [DEPTH:0]  en_n;
    wire term_q;

    DFF_ENAR cell_termination(
        .D  (|{bits[0], term_q, locked}),
        .CLK(clk_sar),
        .EN (1),
        .RST(!start_n),
        .QP (term_q)
        );

    sarcell cell_0 (
        .start_n(start_n),
        .clk    (clk_sar),
        .a      (comp),
        .shift  (bits[1]),
        .en_n   (en_n[0]),
        .k      (bits[0])
    );
    genvar i;
    generate
        for(i=1; i<DEPTH; i=i+1) begin: gen_sarcell
            sarcell cell_i (
                .start_n(start_n),
                .clk    (clk_sar),
                .a      (comp),
                .shift  (bits[i+1]),
                .en_n   (en_n[i]),
                .k      (bits[i])
            );
            assign en_n[i] = |{bits[i-1], en_n[i-1]};
        end
    endgenerate
    assign en_n[DEPTH] = |{bits[DEPTH-1], en_n[DEPTH-1]};
    assign en_n[0] = stop;
    assign stop = term_q | locked;

    sarcell #(1) cell_last (
        .start_n(start_n),
        .clk    (clk_sar),
        .a      (comp),
        .shift  (1),
        .en_n   (en_n[DEPTH]),
        .k      (bits[DEPTH])
    );

endmodule // sar_test

 

Leave a Reply