Monday, March 31, 2014

some basic verilog syntax

1) module
module dataProcess (
    din  ,
    dout ,
    dio
);

input  din  ;
output dout ;
inout  dio  ;

wire din  ;
wire dout ;
// reg dout ;
wire dio  ;

endmodule

2) combinational logic
input  clk  ;
input  mode ;
output sclk ;

wire clk  ;
wire mode ;
wire sclk ;

reg clk_en;

// generate sclk
assign sclk = (clk_en == 1'b1) ? clk : 1'b0;

always @(mode)
//verilog 2000
//always @(*)
begin
    case (mode)
        0 : begin
            clk_en = 1'b0;
        end
        1 : begin
            clk_en = 1'b1;
        end

        default : begin
            clk_en = 1'b0;
        end
    endcase
end

endmodule

3) timing logic
module dff_1 (
    clk   ,
    rst_n ,
    din   ,
    dout
);

input  clk   ;
input  rst_n ;
input  din   ;
output dout  ;

wire clk   ;
wire rst_n ;
wire din   ;
reg  dout  ;

always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        dout <= 1'b0;
    else
        dout <= din;
end

endmodule

4) tristate gate
module dataProcess (
    sclk  ,
    rst_n ,
    rw    ,
    sdio
);

input sclk  ;
input rst_n ;
input rw    ;
inout sdio  ;

wire sclk  ;
wire rst_n ;
wire rw    ;
wire sdio  ;

wire       sdi    ;
reg        sdo    ;
reg        sdo_en ;
reg  [7:0] data   ;

//generate sdio
assign sdio = (sdo_en == 1'b1) ? sdo : 1'bz;

assign sdi  = sdio;

always @(posedge sclk or negedge rst_n) begin
    if(rst_n == 1'b0)
        data <= 'h0;
    else begin
        if(rw == 1'b0)
            data <= {data[6:0], sdi};
        else
            data <= {data[6:0], 1'b0};
    end
end

always @(posedge sclk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        sdo <= 1'b0;
        sdo_en <= 1'b0;
    end
    else begin
        if(rw == 1'b1) begin
            sdo    <= data[7];
            sdo_en <= 1'b1;
        end
        else begin
            sdo    <= 1'b0;
            sdo_en <= 1'b0;
        end
    end
end

endmodule

5) module calling function
///////////////////////////////////////////////////////
// module user_pkg contains the function
///////////////////////////////////////////////////////
module user_pkg;

function [31:0] factorial;
input [3:0] operand;
reg   [3:0] index  ;
begin
    factorial = operand ? 1 : 0;
    for(index = 2; index <= operand; index = index + 1)
        factorial = index * factorial;
end
endfunction

endmodule

///////////////////////////////////////////////////////
// module calling package
///////////////////////////////////////////////////////
module test_package (
    n      ,
    result
);

input  [3:0 ] n      ;
output [31:0] result ;

wire [3:0 ] n      ;
reg  [31:0] result ;

always @(n) begin
    result = n * user_pkg.factorial(n) / ((n * 2) + 1);
end

endmodule

6) module calling task
///////////////////////////////////////////////////////
// module user_pkg contains task
///////////////////////////////////////////////////////
module user_pkg;

task segment_dec;
input  [3:0] bcd    ;
output [6:0] segment;
begin
    case(bcd)
        //decode from bcd to segment
        4'h0: segment = 7'b1000000;
        4'h1: segment = 7'b1111001;
        4'h2: segment = 7'b0100100;
        4'h3: segment = 7'b0110000;
        4'h4: segment = 7'b0011001;
        4'h5: segment = 7'b0010010;
        4'h6: segment = 7'b0000010;
        4'h7: segment = 7'b1111000;
        4'h8: segment = 7'b0000000;
        4'h9: segment = 7'b0010000;
        default: segment = 7'b1000000;
    endcase
end
endtask

endmodule

///////////////////////////////////////////////////////
// module calling task
///////////////////////////////////////////////////////
module bcd2segment (
    bcd     ,
    segment
);

input  [3:0] bcd     ;
output [6:0] segment ;

wire [3:0] bcd     ;
reg  [6:0] segment ;

always @(bcd) begin
    user_pkg.segment_dec(bcd, segment);
end

endmodule

7) parameter
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
    clk     ,
    rst_n   ,
    clk_out
);

parameter N = 12499999;

input  clk     ;
input  rst_n   ;
output clk_out ;

wire clk     ;
wire rst_n   ;
reg  clk_out ;

integer clk_cnt;

always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        clk_cnt <= 0;
        clk_out <= 1'b0;
    end
    else begin
        //when counter reaches to half second,
        //need to reset the counter to 0
        if(clk_cnt == N) begin
            clk_cnt <= 0;
            clk_out <= ~clk_out;
        end
        else begin
            clk_cnt <= clk_cnt + 1;
            clk_out <= clk_out;
        end
    end
end

endmodule

/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
    clk     ,
    rst_n   ,
    clk_out
);

parameter N = 20;

input  clk     ;
input  rst_n   ;
output clk_out ;

wire clk     ;
wire rst_n   ;
wire clk_out ;

//instance clock dividor
clk_div #(
    //verilog 2000
    //.N(N)

    N
) u_clk_div (
    .clk     (clk     ) ,
    .rst_n   (rst_n   ) ,
    .clk_out (clk_out )
);

endmodule

8) instance module
/////////////////////////////////////////////////////////////////
//clk dividor
/////////////////////////////////////////////////////////////////
module clk_div (
    clk     ,
    rst_n   ,
    clk_out
);

input  clk     ;
input  rst_n   ;
output clk_out ;

wire clk     ;
wire rst_n   ;
reg  clk_out ;

always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        clk_out <= 1'b0;
    end
    else begin
        clk_out <= ~clk_out;
    end
end

endmodule

/////////////////////////////////////////////////////////////////
//top
/////////////////////////////////////////////////////////////////
module top (
    clk     ,
    rst_n   ,
    clk_out
);

input  clk     ;
input  rst_n   ;
output clk_out ;

wire clk     ;
wire rst_n   ;
wire clk_out ;

//instance clock dividor
clk_div u_clk_div (
    .clk     (clk     ) ,
    .rst_n   (rst_n   ) ,
    .clk_out (clk_out )
);

endmodule

9) ifdef
`define M7 7
module bcd2segment (
    bcd     ,
    segment
);

input  [3:0    ] bcd    ;
output [`M7-1:0] segment;

wire [3:0    ] bcd    ;
reg  [`M7-1:0] segment;

always @(bcd) begin
    case(bcd)
`ifdef M7
        //decode from bcd to segment
        4'h0: segment = 7'b1111111;
        4'h1: segment = 7'b1111001;
        4'h2: segment = 7'b0100100;
        4'h3: segment = 7'b0110000;
        4'h4: segment = 7'b0011001;
        4'h5: segment = 7'b0010010;
        4'h6: segment = 7'b0000010;
        4'h7: segment = 7'b1111000;
        4'h8: segment = 7'b0000000;
        4'h9: segment = 7'b0010000;
        //for other unknown selectors, set counter to 0
        default: segment = 7'b1111111;
`else
        //decode from bcd to segment
        4'h0: segment = 8'b11111111;
        4'h1: segment = 8'b11111001;
        4'h2: segment = 8'b10100100;
        4'h3: segment = 8'b10110000;
        4'h4: segment = 8'b10011001;
        4'h5: segment = 8'b10010010;
        4'h6: segment = 8'b10000010;
        4'h7: segment = 8'b11111000;
        4'h8: segment = 8'b10000000;
        4'h9: segment = 8'b10010000;
        //for other unknown selectors, set counter to 0
        default: segment = 8'b11111111;
`endif
    endcase
end

endmodule

10) parameter used as data width
`define M7
module bcd2segment (
    bcd     ,
    segment
);

`ifdef M7
parameter M = 7;
`else
parameter M = 8;
`endif

input  [3:0  ] bcd    ;
output [M-1:0] segment;

wire [3:0  ] bcd    ;
reg  [M-1:0] segment;

always @(bcd) begin
    case(bcd)
`ifdef M7
        //decode from bcd to segment
        4'h0: segment = 7'b1111111;
        4'h1: segment = 7'b1111001;
        4'h2: segment = 7'b0100100;
        4'h3: segment = 7'b0110000;
        4'h4: segment = 7'b0011001;
        4'h5: segment = 7'b0010010;
        4'h6: segment = 7'b0000010;
        4'h7: segment = 7'b1111000;
        4'h8: segment = 7'b0000000;
        4'h9: segment = 7'b0010000;
        //for other unknown selectors, set counter to 0
        default: segment = 7'b1111111;
`else
        //decode from bcd to segment
        4'h0: segment = 8'b11111111;
        4'h1: segment = 8'b11111001;
        4'h2: segment = 8'b10100100;
        4'h3: segment = 8'b10110000;
        4'h4: segment = 8'b10011001;
        4'h5: segment = 8'b10010010;
        4'h6: segment = 8'b10000010;
        4'h7: segment = 8'b11111000;
        4'h8: segment = 8'b10000000;
        4'h9: segment = 8'b10010000;
        //for other unknown selectors, set counter to 0
        default: segment = 8'b11111111;
`endif
    endcase
end

endmodule

31) testbench
/////////////////////////////////////////////////////////////////
//DUT
/////////////////////////////////////////////////////////////////
module adder (
    clk    ,
    rst_n  ,
    enable ,
    a      ,
    b      ,
    s      ,
    cout  
);

input        clk    ;
input        rst_n  ;
input        enable ;
input  [3:0] a      ;
input  [3:0] b      ;
output [3:0] s      ;
output       cout   ;

wire       clk    ;
wire       rst_n  ;
wire       enable ;
wire [3:0] a      ;
wire [3:0] b      ;
wire [3:0] s      ;
wire       cout   ;

reg  [4:0] sum    ;

assign s = sum[3:0];
assign cout = sum[4];

always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        sum <= 5'h0;
    else begin
        if(enable == 1)
            sum <= a + b;
    end
end

endmodule

/////////////////////////////////////////////////////////////////
//tb
/////////////////////////////////////////////////////////////////
module tb_adder();

reg        clk    ;
reg        rst_n  ;
reg        enable ;
reg  [3:0] a      ;
reg  [3:0] b      ;
wire [3:0] s      ;
wire       cout   ;

adder u_adder (
    .clk    (clk    ) ,
    .rst_n  (rst_n  ) ,
    .enable (enable ) ,
    .a      (a      ) ,
    .b      (b      ) ,
    .s      (s      ) ,
    .cout   (cout   )
);

initial begin
    clk = 1'b0;
    forever #6.67 clk = ~clk;
end


initial begin
    rst_n = 1'b0;
    #600;
    rst_n = 1'b1;
end

integer i;
integer j;
initial begin
    enable <= 1'b0;
    a <= 'h0;
    b <= 'h0;
    @(posedge rst_n);
    @(negedge clk)
    for(i=0; i<16; i=i+1) begin
        for(j=0; j<16; j=j+1) begin
            @(negedge clk);
            a = i[3:0];
            b = j[3:0];
            enable = 1'b0;
            @(posedge clk);
            #1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
            @(negedge clk);
            enable = 1'b1;
            @(posedge clk);
            #1 $display("a = %d, b = %d, enable = %d, s = %d, cout = %d", a, b, enable, s, cout);
        end
    end
    #100;
    $finish();
end

endmodule

No comments:

Post a Comment