2025华为海思数字IC面经

前两面是流程完全相同而面试官不同的技术面,三面为主管面。

一面 1h

纯项目,A4纸边画边讲,提问也针对项目细节不断往深挖掘

手撕:同步FIFO,同一周期内,写0-1个数据,读0-2个数据

verilog 复制代码
module sync_fifo_ptr #(
    parameter DATA_WIDTH = 8,    // 数据位宽
    parameter FIFO_DEPTH = 16    // FIFO深度(必须是2的幂)
)(
    input  wire                     clk,        // 时钟
    input  wire                     rst_n,      // 异步复位(低有效)
    input  wire                     wr_en,      // 写使能(0或1)
    input  wire [DATA_WIDTH-1:0]    wr_data,    // 写数据
    input  wire [1:0]               rd_en,      // 读使能(0、1或2)
    output wire [DATA_WIDTH-1:0]    rd_data0,   // 读数据0
    output wire [DATA_WIDTH-1:0]    rd_data1,   // 读数据1
    output wire                     empty,      // 空标志
    output wire                     full        // 满标志
);

    // 计算地址宽度
    localparam ADDR_WIDTH = $clog2(FIFO_DEPTH);
    
    // 存储器
    reg [DATA_WIDTH-1:0] mem [0:FIFO_DEPTH-1];
    
    // 读写指针(扩展一位用于空满判断)
    reg [ADDR_WIDTH:0] wr_ptr = 0;  // MSB用于区分绕回
    reg [ADDR_WIDTH:0] rd_ptr = 0;  // MSB用于区分绕回
    
    // 读数据寄存器
    reg [DATA_WIDTH-1:0] rd0_reg;
    reg [DATA_WIDTH-1:0] rd1_reg;
    
    // 空满判断
    assign empty = (wr_ptr == rd_ptr);
    assign full  = ((wr_ptr[ADDR_WIDTH-1:0] == rd_ptr[ADDR_WIDTH-1:0]) && 
                   (wr_ptr[ADDR_WIDTH] != rd_ptr[ADDR_WIDTH]));
    
    // 读数据输出
    assign rd_data0 = rd0_reg;
    assign rd_data1 = rd1_reg;
    
    // 写操作
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            wr_ptr <= 0;
        end else if (wr_en && !full) begin
            mem[wr_ptr[ADDR_WIDTH-1:0]] <= wr_data;
            wr_ptr <= wr_ptr + 1;
        end
    end
    
    // 读操作
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rd_ptr <= 0;
            rd0_reg <= 0;
            rd1_reg <= 0;
        end else begin
            case (rd_en)
                2'd1: begin // 读1个数据
                    if (!empty) begin
                        rd0_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
                        rd_ptr <= rd_ptr + 1;
                        rd1_reg <= 0;
                    end else begin
                        rd0_reg <= 0;
                        rd1_reg <= 0;
                    end
                end
                2'd2: begin // 读2个数据
                    if (!empty) begin
                        rd0_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
                        
                        // 检查是否有第二个数据可读
                        if ((rd_ptr + 1) != wr_ptr) begin
                            rd1_reg <= mem[(rd_ptr + 1)[ADDR_WIDTH-1:0]];
                            rd_ptr <= rd_ptr + 2;
                        end else begin
                            rd1_reg <= 0;
                            rd_ptr <= rd_ptr + 1;
                        end
                    end else begin
                        rd0_reg <= 0;
                        rd1_reg <= 0;
                    end
                end
                default: begin // 不读
                    rd0_reg <= 0;
                    rd1_reg <= 0;
                end
            endcase
        end
    end

endmodule

二面 1h

纯项目,会问一面重点讲的哪一个,换另外的详细讲

手撕:深度32的SRAM,用两个拼成深度64

verilog 复制代码
module sram_64xN #(
    parameter DATA_WIDTH = 8  // 数据位宽
)(
    input  wire                 clk,      // 时钟
    input  wire                 cen,      // 片选信号(低有效)
    input  wire                 wen,      // 写使能(低有效)
    input  wire [5:0]           addr,     // 6位地址(0-63)
    input  wire [DATA_WIDTH-1:0] wdata,   // 写数据
    output wire [DATA_WIDTH-1:0] rdata    // 读数据
);

    // 内部信号定义
    wire sram0_cen;  // SRAM0片选
    wire sram1_cen;  // SRAM1片选
    wire [DATA_WIDTH-1:0] sram0_rdata; // SRAM0读数据
    wire [DATA_WIDTH-1:0] sram1_rdata; // SRAM1读数据
    
    // 地址最高位作为SRAM选择
    // addr[5]=0: 选择SRAM0 (地址0-31)
    // addr[5]=1: 选择SRAM1 (地址32-63)
    
    // SRAM0片选逻辑:当cen有效且地址高位为0时选中
    assign sram0_cen = cen | addr[5];
    
    // SRAM1片选逻辑:当cen有效且地址高位为1时选中
    assign sram1_cen = cen | ~addr[5];
    
    // 实例化两个深度32的SRAM
    sram_32xN #(
        .DATA_WIDTH(DATA_WIDTH)
    ) sram0 (
        .clk(clk),
        .cen(sram0_cen),
        .wen(wen),
        .addr(addr[4:0]),  // 低5位地址
        .wdata(wdata),
        .rdata(sram0_rdata)
    );
    
    sram_32xN #(
        .DATA_WIDTH(DATA_WIDTH)
    ) sram1 (
        .clk(clk),
        .cen(sram1_cen),
        .wen(wen),
        .addr(addr[4:0]),  // 低5位地址
        .wdata(wdata),
        .rdata(sram1_rdata)
    );
    
    // 输出数据选择
    assign rdata = addr[5] ? sram1_rdata : sram0_rdata;

endmodule

// 深度32的SRAM模型
module sram_32xN #(
    parameter DATA_WIDTH = 8
)(
    input  wire                 clk,
    input  wire                 cen,      // 片选(低有效)
    input  wire                 wen,      // 写使能(低有效)
    input  wire [4:0]           addr,     // 5位地址
    input  wire [DATA_WIDTH-1:0] wdata,
    output reg  [DATA_WIDTH-1:0] rdata
);

    // 32xN存储器阵列
    reg [DATA_WIDTH-1:0] mem [0:31];
    
    // 写操作
    always @(posedge clk) begin
        if (!cen && !wen) begin
            mem[addr] <= wdata;
        end
    end
    
    // 读操作
    always @(posedge clk) begin
        if (!cen && wen) begin
            rdata <= mem[addr];
        end else begin
            rdata <= {DATA_WIDTH{1'bz}}; // 高阻态当未选中时
        end
    end

endmodule

三面主管面 30min

都做过什么项目

比赛经历

比赛或项目中的合作

比赛或项目中较大的挫折或困难

如何看待华为的奋斗者文化

Tips:如果有笔试题,还需要把所有笔试题看一遍,技术面过程可能抽题问。

相关推荐
fpga和matlab3 小时前
FPGA时序约束分析4——Reg2Reg路径的建立时间与保持时间分析
fpga开发·reg2reg·建立时间·保持时间
伊宇韵4 小时前
FPGA - GTX收发器-K码 以及 IBERT IP核使用
fpga开发
门外的兔子4 小时前
【FPGA】Quartus Prime Lite 23.1 最新版 安装教程 ModelSim_18.1 下载安装 + 联调仿真教程 + 详细安装教程 2025最新
嵌入式硬件·fpga开发·1024程序员节
NurDroid4 小时前
300个fpga练手项目推荐
fpga开发
&Cheems4 小时前
Vivado 使用教程
fpga开发
Damon小智6 小时前
鸿蒙元服务深度实践:跨端唤醒与状态共享的设计模式
华为·设计模式·harmonyos
广然7 小时前
跨厂商(华为 & H3C)防火墙 GRE 隧道部署
网络·华为·防火墙·h3c
Yeats_Liao7 小时前
华为开源自研AI框架昇思MindSpore应用案例:跑通Vision Transformer图像分类
人工智能·华为·transformer
星释7 小时前
鸿蒙Flutter三方库适配指南:07.插件开发
flutter·华为·harmonyos