华为面试手撕:窄传输

传送
主要由选通信号strobe,case就可以了,当寄存器中数据大于等于8个字节,就输出一次

module narrow_trans(
    input  clk,
    input rst_n,

    input [31 : 0] i_data,
    input [3 : 0] i_data_strobe,
    output reg [63 : 0] o_data,
    output reg o_vld
);
    //==============defination
    reg [3 : 0] cnt;
    //==============combinal logic
    
    //==============sequential logic
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) o_data <= 'd0;
        else begin
            case(i_data_strobe)
                4'b0000 : o_data <= o_data;
                4'b0001 : o_data <= {o_data, i_data[7 : 0]};
                4'b0010 : o_data <= {o_data, i_data[15 : 8]};
                4'b0011 : o_data <= {o_data, i_data[15 : 0]};
                4'b0100 : o_data <= {o_data, i_data[23 : 16]};
                4'b0101 : o_data <= {o_data, i_data[23 : 16], i_data[7 : 0]};
                4'b0110 : o_data <= {o_data, i_data[23 : 8]};
                4'b0111 : o_data <= {o_data, i_data[23 : 0]};
                4'b1000 : o_data <= {o_data, i_data[31 : 24]};
                4'b1001 : o_data <= {o_data, i_data[31 : 24], i_data[7 : 0]};
                4'b1010 : o_data <= {o_data, i_data[31 : 24], i_data[15 : 8]};
                4'b1011 : o_data <= {o_data, i_data[31 : 24], i_data[15 : 0]};
                4'b1100 : o_data <= {o_data, i_data[31 : 16]};
                4'b1101 : o_data <= {o_data, i_data[31 : 16], i_data[7 : 0]};
                4'b1110 : o_data <= {o_data, i_data[31 : 8]};
                4'b1111 : o_data <= {o_data, i_data[31 : 0]};
            endcase
        end
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) cnt <= 'd0;
        else begin
            if(cnt >= 8) begin
                case(i_data_strobe)
                    4'b0000 : cnt <= cnt - 'd8;
                    4'b0001 : cnt <= cnt - 'd8 + 'd1;
                    4'b0010 : cnt <= cnt - 'd8 + 'd1;
                    4'b0011 : cnt <= cnt - 'd8 + 'd2;
                    4'b0100 : cnt <= cnt - 'd8 + 'd1;
                    4'b0101 : cnt <= cnt - 'd8 + 'd2;
                    4'b0110 : cnt <= cnt - 'd8 + 'd2;
                    4'b0111 : cnt <= cnt - 'd8 + 'd3;
                    4'b1000 : cnt <= cnt - 'd8 + 'd1;
                    4'b1001 : cnt <= cnt - 'd8 + 'd2;
                    4'b1010 : cnt <= cnt - 'd8 + 'd2;
                    4'b1011 : cnt <= cnt - 'd8 + 'd3;
                    4'b1100 : cnt <= cnt - 'd8 + 'd2;
                    4'b1101 : cnt <= cnt - 'd8 + 'd3;
                    4'b1110 : cnt <= cnt - 'd8 + 'd3;
                    4'b1111 : cnt <= cnt - 'd8 + 'd4;
                endcase
            end
            else begin
                case(i_data_strobe)
                    4'b0000 : cnt <= cnt;
                    4'b0001 : cnt <= cnt + 'd1;
                    4'b0010 : cnt <= cnt + 'd1;
                    4'b0011 : cnt <= cnt + 'd2;
                    4'b0100 : cnt <= cnt + 'd1;
                    4'b0101 : cnt <= cnt + 'd2;
                    4'b0110 : cnt <= cnt + 'd2;
                    4'b0111 : cnt <= cnt + 'd3;
                    4'b1000 : cnt <= cnt + 'd1;
                    4'b1001 : cnt <= cnt + 'd2;
                    4'b1010 : cnt <= cnt + 'd2;
                    4'b1011 : cnt <= cnt + 'd3;
                    4'b1100 : cnt <= cnt + 'd2;
                    4'b1101 : cnt <= cnt + 'd3;
                    4'b1110 : cnt <= cnt + 'd3;
                    4'b1111 : cnt <= cnt + 'd4;
                endcase
            end
        end
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) o_vld <= 1'b0;
        else begin
            if(cnt >= 'd8) o_vld <= 1'b1;
            else o_vld <= 1'b0;
        end
    end
endmodule

module tb_narrow_trans();
    //===================parameter
    parameter PERIOD = 20;
    //===================defination
    reg clk, rst_n;
    reg [31 : 0] i_data;
    reg [3 : 0] i_data_strobe;
    wire [63 : 0] o_data;
    wire o_vld;
    //===================logic
    initial begin
        clk = 0;
        rst_n = 0;
        #200 rst_n = 1;
	#500 $finish;
    end
    always #(PERIOD / 2) clk = ~clk;
    initial begin
        @(rst_n);
        data_in(32'habcd_1234, 4'b1010);
        data_in(32'hef67_3482, 4'b1111);
        data_in(32'h6789_3322, 4'b0110);
        data_in(32'hef67_3482, 4'b1100);
        data_in(32'habcd_1234, 4'b1010);
        data_in(32'hef67_3482, 4'b1111);
        data_in(32'h6789_3322, 4'b0110);
        data_in(32'hef67_3482, 4'b1100);
    end

    task data_in(input [31 : 0] data, input [3 : 0] strobe);
        @(posedge clk);
        #1;
        i_data = data;
        i_data_strobe = strobe;
    endtask
    narrow_trans u_narrow_trans(
        .clk(clk),
        .rst_n(rst_n),

        .i_data(i_data),
        .i_data_strobe(i_data_strobe),
        .o_data(o_data),
        .o_vld(o_vld)
    );
`ifdef FSDB
initial begin
	$fsdbDumpfile("narrow_trans.fsdb");
	$fsdbDumpvars;
    	$fsdbDumpMDA();
end
`endif
endmodule 

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值