硬件领域的leetcode:HDLBits 刷题记录

FPGA 系列文章

  • 如果你想学习有关FPGA的专业术语,可以参考这一篇:FPGA专业术语介绍
  • 鼎力推荐Verilog初学者的一个刷题网站,硬件领域的leetcode,能够对编写完的代码进行在线仿真:HDLBits
  • 这是第一遍刷题的记录,之后争取跟着b站课程复盘一遍 \(▔^▔)/


Basics

1.Wire

module top_module( input in, output out );
    assign out = in; 
endmodule

2.Wire4

module top_module( 
    input a,b,c,
    output w,x,y,z );
    assign w = a;
    assign x = b;
    assign y = b;
    assign z = c;
endmodule

3.Notgate

module top_module( input in, output out );
    assign out = ~in;
endmodule

4.Andgate

module top_module( 
    input a, 
    input b, 
    output out );
    assign out = a & b;
endmodule

5.Norgate

module top_module( 
    input a, 
    input b, 
    output out );
    assign out = ~(a | b);
endmodule

6.Xnorgate

module top_module( 
    input a, 
    input b, 
    output out );
    assign out = ~(a ^ b);
endmodule

7.Wire decl
请添加图片描述

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out,
    output out_n   ); 
    wire or_in1;
    wire or_in2;
    wire not_in;
    
    assign or_in1 = a & b;
    assign or_in2 = c & d;
    assign not_in = or_in1 | or_in2;
    
    assign out = not_in;
    assign out_n = ~not_in;
endmodule

8.7458
请添加图片描述

module top_module ( 
    input p1a, p1b, p1c, p1d, p1e, p1f,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    wire orA_in1;
    wire orA_in2;
    wire orB_in1;
    wire orB_in2;
    
    assign orA_in1 = p2c & p2d;
    assign orA_in2 = p2a & p2b;
    assign orB_in1 = p1a & p1b & p1c;
    assign orB_in2 = p1d & p1e & p1f;
    assign p2y = orA_in1 | orA_in2;
    assign p1y = orB_in1 | orB_in2;
endmodule

Vectors

1.Vector0

module top_module ( 
    input wire [2:0] vec,
    output wire [2:0] outv,
    output wire o2,
    output wire o1,
    output wire o0  ); // Module body starts after module declaration
    
    assign outv = vec;
    assign o2 = vec[2];
    assign o1 = vec[1];
    assign o0 = vec[0];
endmodule
  1. Vector1
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    
    assign out_hi[7:0] = in[15:8];
    assign out_lo[7:0] = in[7:0];
endmodule

3.Vector2

module top_module( 
    input [31:0] in,
    output [31:0] out );//

    assign out[31:24] = in[7:0];
    assign out[23:16] = in[15:8];
    assign out[15:8] = in[23:16];
    assign out[7:0] = in[31:24];
endmodule

4.Vectorgates

  • assign中若没有标记多少位,默认全部位参与计算。
  • bitwise对每一位进行逻辑或运算;logical将整个矢量视为布尔值,为空视为0,不为空设为1。
  • 如果 a 的值为 100(二进制,不为空logical视为1),b 的值为000(二进制,为空logical设为0),那么 bitwise = 100(二进制),logical = 1 | 0 = 1。
module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);
    assign out_or_bitwise = a | b;
    assign out_or_logical = a || b;
    assign out_not[2:0] = ~a;
    assign out_not[5:3] = ~b;
endmodule

5.Gates4

module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
    assign out_and = in[3]&in[2]&in[1]&in[0];
    assign out_or = in[3]|in[2]|in[1]|in[0];
    assign out_xor = in[3]^in[2]^in[1]^in[0];
endmodule

6.Vector3

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//

    assign w = {a[4:0],b[4:2]};
    assign x = {b[1:0],c[4:0],d[4]};
    assign y = {d[3:0],e[4:1]};
    assign z = {e[0],f[4:0],2'b11};
endmodule

7.Vectorr

module top_module( 
    input [7:0] in,
    output [7:0] out
);
    always @(*) begin
        for(integer i = 0; i < 8; i++)begin
            out[i]=in[7-i];
        end
    end
endmodule

8.Vector4

module top_module (
    input [7:0] in,
    output [31:0] out );//

    assign out = {{24{in[7]}},in[7:0]};

endmodule

9.Vector5

module top_module (
    input a, b, c, d, e,
    output [24:0] out );//

    assign out = ~{5{a,b,c,d,e}}^{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}};

endmodule

Modules:Hierarchy

1.Module

module top_module ( input a, input b, output out );
    mod_a k(.in1(a),.in2(b),.out(out) );
endmodule

2.Module pos

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a k(out1,out2,a,b,c,d);
endmodule

3.Module name

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a k(.out1(out1),.out2(out2),.in1(a),.in2(b),.in3(c),.in4(d));
endmodule

4.Module shift

module top_module ( input clk, input d, output q );
    wire mydff_out1;
    wire mydff_out2;
    my_dff k1(clk, d, mydff_out1);
    my_dff k2(clk, mydff_out1, mydff_out2);
    my_dff k3(clk, mydff_out2, q);
endmodule

5.Module shift8

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);
    wire [7:0] mydff8_out1;
    wire [7:0] mydff8_out2;
    wire [7:0] mydff8_out3;
    
    my_dff8 k1(clk,d,mydff8_out1);
    my_dff8 k2(clk,mydff8_out1,mydff8_out2);
    my_dff8 k3(clk,mydff8_out2,mydff8_out3);
    
    always @(*) begin
        case(sel)
            2'b00:
                q=d;
            2'b01:
                q=mydff8_out1;                
            2'b10:
                q=mydff8_out2;                
            2'b11:
                q=mydff8_out3;                
        endcase
    end
endmodule

6.Module add

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire add16_out;
    add16 k1(a[15:0],b[15:0],0,sum[15:0],add16_out);
    add16 k2(a[31:16],b[31:16],add16_out,sum[31:16]);
endmodule

7.Module fadd

  • {cout, sum}:这是一个赋值的目标,在代码中表示将右侧表达式的进位输出和的结果赋值给cout和sum。
module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire add16_out;
    add16 k1(a[15:0],b[15:0],0,sum[15:0],add16_out);
    add16 k2(a[31:16],b[31:16],add16_out,sum[31:16]);
endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );
    assign {cout, sum} = a + b + cin;
endmodule

8.Module cseladd

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire add16_out1;
    wire [15:0] add16_out2;
    wire [15:0] add16_out3;
    
    add16 k1(a[15:0],b[15:0],0,sum[15:0],add16_out1);
    add16 k2(a[31:16],b[31:16],0,add16_out2[15:0]);
    add16 k3(a[31:16],b[31:16],1,add16_out3[15:0]);
    
    always @(*) begin
        case(add16_out1)
            1'b0:
                sum[31:16]=add16_out2[15:0];
            1'b1:
                sum[31:16]=add16_out3[15:0];
        endcase
    end
endmodule

9.Module addsub

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire [31:0] xor_output;
    wire add16_out;
    
    always @(*) begin
        for(integer i = 0; i < 32; i++)begin
            xor_output[i] = b[i] ^ sub;
        end
    end
    
    add16 k1(a[15:0],xor_output[15:0],sub,sum[15:0],add16_out);
    add16 k2(a[31:16],xor_output[31:16],add16_out,sum[31:16]);
endmodule

Procedures

1.Alwaysblock1

module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
    assign out_assign = a & b;
    always @(*) out_alwaysblock = a & b;
endmodule

2.Alwaysblock2

module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   );
    
    assign out_assign = a ^ b;
    always @(*) out_always_comb = a ^ b;
    always @(posedge clk) out_always_ff = a ^ b;
endmodule

3.Always if

module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always   ); 
    reg temp_assign; // 中间变量
    always @(*) begin
        case(sel_b1&sel_b2)
            1'b1:     
                begin
                temp_assign = b;
                out_always = b;
                end
            default:
                begin
                temp_assign = a;
                out_always = a;
                end
        endcase
    end
    assign out_assign = temp_assign;
endmodule

4.Always if2

module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        if (cpu_overheated)
           shut_off_computer = 1;
        else
           shut_off_computer = 0;
    end

    always @(*) begin
        if (~arrived)
           keep_driving = ~gas_tank_empty;
        else
           keep_driving = 0;
    end

endmodule

5.Always case

module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );//

    always @(*) begin  // This is a combinational circuit
        case(sel[2:0])
            3'b000:
                out=data0;
            3'b001:
                out=data1;
            3'b010:
                out=data2;
            3'b011:
                out=data3;
            3'b100:
                out=data4;
            3'b101:
                out=data5;
            default:
                out=3'b0;
        endcase
    end
endmodule

6.Always case2

module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always @(*) begin
        case(1)
            in[0]:pos = 0;
            in[1]:pos = 1;
            in[2]:pos = 2;
            in[3]:pos = 3;
            default:pos = 0;
        endcase
    end
endmodule

7.Always casez

module top_module (
    input [7:0] in,
    output reg [2:0] pos );
    always @(*) begin
        casez(in[7:0])
            8'bzzzzzzz1:
                pos = 0;
            8'bzzzzzz1z:
                pos = 1;
            8'bzzzzz1zz:
                pos = 2;
            8'bzzzz1zzz:
                pos = 3;
            8'bzzz1zzzz:
                pos = 4;
            8'bzz1zzzzz:
                pos = 5;
            8'bz1zzzzzz:
                pos = 6;
            8'b1zzzzzzz:
                pos = 7;
            default:
                pos = 0;
        endcase
    end
endmodule

8.Always nolatches

  • 防止默认up,down,left,right不变生成latch,需要给up,down,left,right赋初始值 , 或者在每一个case中都为up,down,left,right赋值,后者由于代码冗长一般不推荐使用。
  • case附带的多条语句需要用begin-end包围。
// 给up,down,left,right赋初始值
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
    always @(*) begin 
    left=0;down=0;right=0;up=0;
       case(scancode)
           16'he06b:
                left=1;
           16'he072:
                down=1;
           16'he074:
                right=1;
           16'he075:
                up=1;
       endcase
    end
endmodule
// 在每一个case中都为up,down,left,right赋值
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
    always @(*) begin 
       case(scancode)
           16'he06b:
               begin
                left=1;
                down=0;
                right=0;
                up=0;
               end
           16'he072:
               begin
               left=0;
               down=1;
               right=0;
               up=0;
               end
           16'he074:
               begin
               left=0;
               down=0;
               right=1;
               up=0;
               end
           16'he075:
               begin
               left=0;
               down=0;
               right=0;
               up=1;
               end
           default:
               begin
               left=0;
               down=0;
               right=0;
               up=0;
               end
       endcase
    end
endmodule

More Verilog Features

1.Conditional

module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//

    wire [7:0] min_ab;
    wire [7:0] min_cd;
    assign min_ab = (a < b ? a : b);
    assign min_cd = (c < d ? c : d);
    assign min = (min_ab <min_cd ? min_ab : min_cd);
    // assign intermediate_result1 = compare? true: false;

endmodule

2.Reduction

module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^ in[7:0];
endmodule

3.Gates100

module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = &in[99:0];
    assign out_or = |in[99:0];
    assign out_xor = ^in[99:0];
endmodule

4.Vector100r

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    always @(*) begin
        for(integer i = 0; i <100; i++)begin
            out[i] = in[99-i];
        end
    end
endmodule

5.Popcount255

  • 注意将out初始化为0,否则会产生锁存器使得结果不正确。
module top_module( 
    input [254:0] in,
    output [7:0] out );
    always @(*) begin
        out = 0;
        for(integer i = 0; i < 255; i++) begin
            if(in[i] == 1'b1)
                out++;
        end
    end
endmodule

7.Adder100i

  • generate用于实例化,和for循环的用法基本一致。不同之处有两点,其一为循环变量需要在循环外用genvar关键字声明,其二为需要一个实例化名称。
module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    genvar i;
    generate
        for(i=0;i<100;i++) begin:adder
            if(i==0)
                assign{cout[0],sum[0]}=a[0]+b[0]+cin;
            else
                assign{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];
        end           
    endgenerate
endmodule

8.Bcdadd100

  • 使用1位加法器合成100位加法器的典型案例,如果能独立写出来,说明你已经对上述内容基本掌握了。
module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    wire [99:0] temp;
    genvar i;
    generate
        for(i=0;i<100;i++) begin:bcd_fadd
            if(i == 0)
                bcd_fadd k(a[3:0],b[3:0],cin,temp[0],sum[3:0]);
            else
                bcd_fadd k(a[4*i+3:4*i],b[4*i+3:4*i],temp[i-1],temp[i],sum[4*i+3:4*i]);
        end
        assign cout=temp[99];
    endgenerate
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值