1. 4位加法器

adder.v

module adder (
        input wire [3:0] A,B,
        input Ci,
        output wire [3:0] Sum,
        output Co

    );

    assign {Co,Sum} = A+B+Ci;
endmodule

tb_adder.v

`timescale 1ns/1ns
`include"../rtl/adder.v"
module adder_tb;
    reg [3:0]a,b;
    reg ci;
    wire [3:0]Sum;
    wire Co;
    integer i,j;
    adder U1(.A(a),
             .B(b),
             .Ci(ci),
             .Sum(Sum),
             .Co(Co));
    initial begin
        a=0;
        b=0;
        for(i=0;i<16;i=i+1)
            for(j=0;j<16;j=j+1) begin
                ci=0;
                a=i;
                b=j;
                #10;
                ci=1;
                a=i;
                b=j;
                #10;
            end
        $finish;
    end
    initial begin
        $monitor("%d+%d+%d=%d%d",a,b,ci,Co,Sum);
    end
    initial begin
        $dumpfile("adder.vcd");
        $dumpvars(0,adder_tb);

    end
endmodule

2. 4位BCD加法器

BCDadder.v

module BCDadder (
	input [3:0]A,B,
	input Cin,
	output [3:0] Sum,
	output Co

);
	
	assign {Co,Sum} = ((A+B+Cin)>9)?(A+B+Cin+6):(A+B+Cin);
endmodule

tb_BCD_adder.v

`timescale 1ns/1ns
`include "../rtl/BCDadder.v"
module tb_BCD_adder();
    reg [3:0]A,B;
    reg Cin;
    wire [3:0] 	Sum;
    wire       	Co;
    integer i,j;
    BCDadder u_BCDadder(
                 .A   	( A    ),
                 .B   	( B    ),
                 .Cin 	( Cin  ),
                 .Sum 	( Sum  ),
                 .Co  	( Co   )
             );
    initial begin
        for(i=0;i<10;i=i+1) begin
            for(j=0;j<10;j=j+1) begin
                Cin=0;
                A=i;
                B=j;
                #10;
                $display("A=%d,B=%d,Cin=%d,Sum=%d,Co=%d",A,B,Cin,Sum,Co);
                Cin=1;
                #10;
                $display("A=%d,B=%d,Cin=%d,Sum=%d,Co=%d",A,B,Cin,Sum,Co);
            end
        end
        $finish;
    end
    initial begin
        $dumpfile("dump.vcd");
        $dumpvars(0, tb_BCD_adder);

    end
endmodule

3. 八选一数据选择器

MUX81.v

 module MUX81 (
         input [7:0]IN,
         input [2:0]SEL,
         output OUT
     );
     assign OUT =SEL[2]?
					(SEL[1]?SEL[0]?IN[7]:IN[6]:SEL[0]?IN[5]:IN[4]):
					(SEL[1]?SEL[0]?IN[3]:IN[2]:SEL[0]?IN[1]:IN[0]);
 endmodule

4. 3-8译码器

Decode138.v


module Decode138 (
        input A,B,C,G1,G2An,G2Bn,
        output [7:0] Y
    );
    assign Y = (G1&(~G2An)&(~G2Bn))?(~(8'b00000001<<{C,B,A})):(8'b11111111);
endmodule

tb_Decode138.v

`include "../rtl/Decode138.v"
`timescale 1ns / 1ns
module tb_Decode138();
    reg A,B,C,G1,G2An,G2Bn;
    wire [7:0] 	Y;
    integer i;
    Decode138 u_Decode138(
                  .A    	( A     ),
                  .B    	( B     ),
                  .C    	( C     ),
                  .G1   	( G1    ),
                  .G2An 	( G2An  ),
                  .G2Bn 	( G2Bn  ),
                  .Y    	( Y     )
              );

    initial begin
        G2An=0;
        G2Bn=0;
        G1=1;
        repeat(10)
            for(i=0;i<7;i=i+1) begin
                {C,B,A}=i;
                #10;
            end
            $finish;
    end
    initial begin
        $dumpfile("dump.vcd");
        $dumpvars(0,tb_Decode138);
    end
endmodule

5. 锁存器

_latch.v

module _latch(
        input D,SET,CLRn,CLK,
        output Q
    );

    assign Q = CLRn ? (SET ? 1:(CLK ? D:Q)):0;
endmodule

tb_latch.v

`timescale 1ns/1ns
`include "../rtl/_latch.v"
module tb_latch;
    reg clk,d,set,clrn;
    wire q;
    integer i,num;
    _latch u1(.CLK(clk),.SET(set),.CLRn(clrn),.D(d),.Q(q));
    initial begin
        set = 1;
        clk =0;
        clrn =0;
        d=0;
        #10 clrn = 1;
        #20 d = 1;
        #10 d = 0;
        #10 set = 0;
        for(i=0;i<200;i=i+1) begin
            num={$random}%10+1;
            #num d=1;
            num={$random}%10+1;
            #num d=0;
        end
        $finish;
    end
    always #10 clk = ~clk;
    
    initial begin
        $dumpfile("latch.vcd");
        $dumpvars(0,tb_latch);
    end
endmodule

6.D触发器

_D_flip_flop.v

module _D_flip_flop(
        input wire D,
        input wire CLK,
        input wire CLRn,
        input wire SET,
        output reg Q
    );
    always @(posedge CLK or negedge CLRn ) begin
        if(!CLRn)
            Q<=0;
        else if(SET)
            Q<=1;
        else if(CLK)
            Q<=D;
        else
            Q<=Q;
    end
endmodule

tb_D_flip_flop.v

`timescale 1ns/1ns
`include "../rtl/_D_flip_flop.v"
module tb_D_flip_flop;
    reg clk,d,set,clrn;
    wire q;
    integer i,num;
    _D_flip_flop u1(.CLK(clk),.SET(set),.CLRn(clrn),.D(d),.Q(q));

    initial begin
        set = 1;
        clk =0;
        clrn =0;
        d=0;
        #10 clrn = 1;
        #20 d = 1;
        #10 d = 0;
        #10 set = 0;
        for(i=0;i<200;i=i+1) begin
            num={$random}%10+1;
            #num d=1;
            num={$random}%10+1;
            #num d=0;
        end
        $finish;
    end
    always #10 clk = ~clk;
    initial begin
        $dumpfile("dump.vcd");
        $dumpvars(0,tb_D_flip_flop);
    end
endmodule

7.模24计数器

_counter.v

module _counter (
        input CLK,
        input Loadn,
        input CLRn,
        input [4:0]D,
        output reg [4:0] Q,
        output reg Co
    );
    always @(posedge CLK,negedge CLRn) begin
        if(~CLRn) begin
            Q <= 0;
            Co <=0;
        end
        else if (~Loadn)
            Q <= D;
        else if(Q==24-1) begin
            Q<=0;
            Co<=1;
        end
        else begin
            Q<=Q+1;
            Co<=0;
        end
    end
endmodule

tb_counter.v

`timescale 1ns / 1ns
`include "../rtl/_counter.v"
module tb_counter();
    reg CLK,Loadn,CLRn;
    reg [4:0]D;
    wire [4:0]Q;
    wire Co;
    _counter u1(
                .CLK(CLK),
                .Loadn(Loadn),
                .CLRn(CLRn),
                .D(D),
                .Q(Q),
                .Co(Co)
            );

    always #10 CLK=~CLK;
    initial begin
        CLK = 0;
        Loadn = 1;
        D = 10;
        CLRn = 0;
        #20 CLRn=1;
        D=0;
        Loadn = 0;
        #20 Loadn = 1;
        #2000;
        $finish;
    end
    initial begin
        $monitor ("%9t ns Q = %d,Co = %d",$time,Q,Co);
    end
    initial begin
        $dumpfile("counter.vcd");
        $dumpvars(0,tb_counter);
    end
endmodule

8.偶数12分频器

even_divide.v

module even_divide(
        input CLK,
        input RSTn,
        output reg CLK_12
    );
    reg [3:0]cnt;
    always@(posedge CLK or negedge RSTn) begin
        if(!RSTn) begin
            cnt<=0;
            CLK_12 <= 0;
        end
        else begin
            if(cnt<5)
                cnt<=cnt+1;
            else begin
                cnt<=0;
                CLK_12 <= ~CLK_12;
            end
        end
    end
endmodule

tb_even_divide.v

`timescale 1ns/1ns
`include "../rtl/even_divide.v"
module tb_even_divide();

    reg CLK,RSTn;
    wire CLK_12;

    even_divide u1(
                    .CLK( CLK),
                    .RSTn( RSTn),
                    .CLK_12( CLK_12)
                );

    always #10 CLK=~CLK;
    initial begin
        CLK = 0;
        RSTn=0;
        #10 RSTn=1;
        #2000;
        $finish;
    end
    initial begin
        $dumpfile("even_divide.vcd");
        $dumpvars(0,tb_even_divide);
    end
endmodule

9.奇数15分频器

odd_divide.v

module odd_divide(
         input CLK,
         input RSTn,
         output CLK_15
     );
     reg [4:0]cnt1;
     reg [4:0]cnt2;
     reg clk1,clk2;
     always @(posedge CLK or negedge RSTn) begin
         if(!RSTn) begin
             cnt1<=0;
             clk1<=0;
         end
         else begin
             if(cnt1<14)
                 cnt1<=cnt1+1;
             else
                 cnt1<=0;
             if(cnt1<7)
                 clk1<=1'b1;
             else
                 clk1<=1'b0;

         end
     end
     always @(negedge CLK or negedge RSTn) begin
         if(!RSTn) begin
             cnt2<=0;
             clk2 <= 0;
         end
         else begin
            if(cnt2<14)
                 cnt2<=cnt2+1;
             else
                 cnt2<=0;
             if(cnt2<7)
                 clk2<=1'b1;
             else
                 clk2<=1'b0;
         end
     end
     assign CLK_15 = clk1 | clk2;
 endmodule

tb_odd_divide.v

`timescale 1ns/1ns
`include "../rtl/odd_divide.v"
module tb_odd_divide();

    reg CLK;
    reg RSTn;
    wire   	CLK_15;
    odd_divide U1(.CLK    	( CLK     ),
                  .RSTn   	( RSTn    ),
                  .CLK_15 	( CLK_15  )
                 );
    always #10 CLK=~CLK;
    initial begin
        CLK=0;
        RSTn=0;
        #20 RSTn=1;
        #1000;
        $finish;
    end
    initial begin
        $dumpfile("dump.vcd");
        $dumpvars(0,tb_odd_divide);
    end
endmodule

10.计数器(状态机写法)

counter.v

module counter(
        input clk,
        input rst_n,
        output [3:0] q,
        output reg co
    );
    parameter s0=0, s1=1, s2=2, s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9;
    reg [3:0] state;
    assign q=state;
    always @(posedge clk,negedge rst_n) begin
        if(!rst_n)
            co<=0;
        else if(state==s9)
            co<=1;
        else
            co<=0;
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            state <= s0;
        end
        else begin
            case(state)
                s0: begin
                    state <= s1;
                end
                s1: begin
                    state <= s2;
                end
                s2: begin
                    state <= s3;
                end
                s3: begin
                    state <= s4;
                end
                s4: begin
                    state <= s5;
                end
                s5: begin
                    state <= s6;
                end
                s6: begin
                    state <= s7;
                end
                s7: begin
                    state <= s8;
                end
                s8: begin
                    state <= s9;
                end
                s9: begin
                    state <= s0;
                end
                default: begin
                    state <= s0;
                end
            endcase
        end
    end

endmodule

tb_counter.v

`timescale 1ns/1ns
`include "../rtl/counter.v"
module tb_counter();
    reg clk,rst_n;
    wire [3:0]q;
    wire co;
    counter counter_inst(
                .clk(clk),
                .rst_n(rst_n),
                .q(q),
                .co(co)
            );
    always #10 clk = ~clk;
    initial begin
        clk=0;
        rst_n=0;
        #10 rst_n=1;
        #1000 $finish;
    end
    initial begin
        $dumpfile("counter.vcd");
        $dumpvars(0,tb_counter);
    end
endmodule

11. 序列检测器(状态机)

检测01101序列

seq.v

module seq(
        input clk,
        input rst_n,
        input data_in,
        output data_out
    );//01101

    parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5;
    reg [3:0]state;
    assign data_out=(state==s5)?1:0;
    always @(posedge clk,negedge rst_n) begin
        if(!rst_n) begin
            state<=s0;
        end
        else begin
            case(state)
                s0:
                    state<=(data_in)?s0:s1;
                s1:
                    state<=(data_in)?s2:s1;
                s2:
                    state<=(data_in)?s3:s1;
                s3:
                    state<=(data_in)?s0:s4;
                s4:
                    state<=(data_in)?s5:s1;
                s5:
                    state<=(data_in)?s3:s1;
                default:
                    state<=s0;
            endcase
        end
    end


endmodule

tb_seq.v

`timescale 1ns/1ns
`include "../rtl/seq.v"
module tb_counter();
    reg clk,rst_n;
    reg data_in;
    wire data_out;
    seq seq_inst(.clk(clk),
                 .rst_n(rst_n),
                 .data_in(data_in),
                 .data_out(data_out)
                );
    always #5 clk = ~clk;
    initial begin
        clk=0;
        rst_n=0;
        data_in=0;
        #10 rst_n=1;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;

        #10 data_in=0;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;
        #10 data_in=0;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=1;
        #10 data_in=0;
        $finish;

    end
    initial begin
        $dumpfile("seq.vcd");
        $dumpvars(0,tb_counter);
    end
endmodule

11. 饮料贩卖机(状态机)

drink.v

module drink(
        input CLK,RSTn,A,B,//A:0.5  ;  B:1
        output reg out1,out2
    );
    parameter s0=0,s1=1,s2=2;
    reg [1:0]state;

    always@(posedge CLK or negedge RSTn)
        if(!RSTn) begin
            out1<=0;
            out2<=0;
            state<=s0;
        end
        else
        case(state)
            s0:					//0.5
                if(A==1&&B==0) begin
                    out1<=0;
                    out2<=0;
                    state<=s1;
                end
                else if(A==0&&B==1) begin
                    out1<=0;
                    out2<=0;
                    state<=s2;
                end
                else if(A==0&&B==0) begin
                    out1<=0;
                    out2<=0;
                    state<=s0;
                end
            s1:					//1
                if(A==1&&B==0) begin
                    out1<=0;
                    out2<=0;
                    state<=s2;
                end
                else if(A==0&&B==1) begin
                    out1<=1;
                    out2<=0;
                    state<=s0;
                end
                else if(A==0&B==0) begin
                    out1<=0;
                    out2<=0;
                    state<=s1;
                end
            s2:					//1.5
                if(A==1&&B==0) begin
                    out1<=1;
                    out2<=0;
                    state<= s0;
                end
                else if(A==0&&B==1) begin
                    out1<=1;
                    out2<=1;
                    state<= s0;
                end
                else if(A==0&&B==0) begin
                    out1<=0;
                    out2<=0;
                    state<=s2;
                end
            default: begin
                out1<=0;
                out2<=0;
                state<=s0;
            end
        endcase
endmodule

tb_drink.v


`timescale 1ns/1ns
`include "../rtl/drink.v"
module tb_drink();

    reg CLK,RSTn,A,B;

    wire out1,out2;
    drink U1(
              .CLK(CLK),
              .RSTn(RSTn),
              .A(A),
              .B(B),
              .out1(out1),
              .out2(out2)
          );
    always #5 CLK=~CLK;
    integer i;
    initial begin
        CLK=0;
        RSTn=0;
        A=0;
        B=0;
        #10 RSTn=1;
        #10 A=1;//0.5+0.5+0.5
        #10 A=0;
        #10 A=1;
        #10 A=0;
        #10 A=1;
        #10 A=0;

        #10 A=1;//0.5+1
        #10 A=0;
        #10 B=1;
        #10 B=0;

        #10 B=1;//1+0.5
        #10 B=0;
        #10 A=1;
        #10 A=0;

        #10 B=1;//1+1
        #10 B=0;
        #10 B=1;
        #10 B=0;

        #10 A=1;//0.5+0.5+1
        #10 A=0;
        #10 A=1;
        #10 A=0;
        #10 B=1;
        #10 B=0;



        #100;
        $finish;
    end
    initial begin
        $dumpfile("drink.vcd");
        $dumpvars(0,tb_drink);
    end
endmodule