1. 程式人生 > 其它 >手撕程式碼——2022樂鑫數字晶片提前批筆試:程式碼題2

手撕程式碼——2022樂鑫數字晶片提前批筆試:程式碼題2

手撕程式碼——2022樂鑫數字晶片提前批筆試:程式碼題2

題目:使用Verilog/SV撰寫如下功能模組;求輸入訊號序列din在din_vld為高電平的時間段內的次小值和次小值出現的次數。介面宣告如下:

module sec_min(

input clk,//時鐘

input rst_n,//復位

input [9:0] din, //10bit 無符號數

input din_vld, //輸入資料有效訊號

output wire [9:0] dout, //次小值

output wire [8:0] cnt //次小值出現的次數。溢位時重新計數

);

verilog程式如下:

module sec_min(

input clk,//時鐘

input rst_n,//復位

input [9:0] din, //10bit 無符號數

input din_vld, //輸入資料有效訊號

output wire [9:0] dout, //次小值

output wire [8:0] cnt //次小值出現的次數。溢位時重新計數

);

reg [9:0] data_temp;
// 快取上個週期訊號
always @(posedge clk ) begin
    if(!rst_n) begin
        data_temp<=0;
    end
    else if(din_vld)begin
        data_temp<=dout;
    end
    else begin
        data_temp<=0;
    end
end

reg [9:0] data_min;
reg [9:0] pre_data_min;
reg start;

//min
always @(posedge clk) begin
    if(!rst_n) begin
        data_min<=9'd0;
        start<=1'b1;
    end
    else if(start&&din_vld)begin
       data_min<=din;
       start<=1'b0;
    end
    else if(din_vld)begin
        if (data_min<din) begin
            data_min<=data_min;
        end
        else begin
            data_min<=din;
        end
    end
    else begin
        data_min<=0;
        start<=1'b1;
    end
end

//pre_min
reg [8:0]count;
reg second;
always @(posedge clk) begin
    if (!rst_n) begin
        pre_data_min<=0;
        second<=1'b0;
        count<=9'd0;
    end
    else if(start&&din_vld)begin
        second<=1'b1;
        pre_data_min<=din;
    end
    else if (second&&(~start)&&din_vld) begin
        if (data_temp<din) begin
            pre_data_min<=din;
            count<=9'd1;
            second<=1'b0;
        end
        else begin
            pre_data_min<=data_temp;
            count<=9'd1;
            second<=1'b0;
        end
    end
    else if (din_vld) begin
        if (din==pre_data_min) begin
            count<=count+1'b1;
            pre_data_min<=pre_data_min;
        end
        else if (din>pre_data_min) begin
            count<=count;
            pre_data_min<=pre_data_min;
        end
        else if (din<data_min) begin
            pre_data_min<=data_min;
            count<=9'd1;
        end
        else if (din==data_min) begin
            count<=count;
            pre_data_min<=pre_data_min;
        end
        else begin
            pre_data_min<=din;
            count<=9'd1;
        end
    end
    else begin
        pre_data_min<=0;
        second<=1'b0;
        count<=9'd0;
    end
end
    assign dout =pre_data_min;
    assign cnt =count;

endmodule

模擬結果如下:


由於TB的資料是按照clk的上升沿變化的,看的時候要往後看一個週期才有效。結果是OK的。

TB可以自己寫然後測試。