1. 程式人生 > 其它 >牛客網FPGA題庫刷題之快速入門題庫(一)1~8題

牛客網FPGA題庫刷題之快速入門題庫(一)1~8題

牛客網FPGA題庫刷題之快速入門題庫(一)1~8題

第一題

題目連結:

四選一多路器

程式碼:

`timescale 1ns/1ns
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output[1:0]mux_out
);
//*************code***********//
    reg [1:0] mux_out_tmp;
    always@(*)begin
        case(sel)
            2'b00:mux_out_tmp = d3;
            2'b01:mux_out_tmp = d2;
            2'b10:mux_out_tmp = d1;
            2'b11:mux_out_tmp = d0;
        endcase
    end
            assign mux_out = mux_out_tmp;

//*************code***********//
endmodule

題目解析:

用case語句實現簡單的四路選擇,always語句裡面需要用reg,所以新建一個reg的temp變數即可

第二題

題目連結

非同步復位的串聯T觸發器

程式碼

`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q
);
//*************code***********//
reg  tmp;
    always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
         tmp <= 0 ;
        end
        else begin
         tmp <= tmp ^ data;
        end
    end

     always@(posedge clk or negedge rst)begin
        if(rst == 1'b0)begin
         q <= 0 ;
        end
        else begin
         q <=tmp ^q;
        end
    end
//*************code***********//
endmodule

題目解析

首先了解T觸發器的特性方程

Qn+1 = T Qn ' +T ' Qn = T⊕Qn (其中Qn為現態,Qn+1為次態) 也就是異或

然後題目是兩個T觸發器,所以第一個的輸出是第二個的輸入

網友的解析:

1、T觸發器是進入的值為1的時候,寄存的值發生翻轉
2、注意非同步復位
3、需要注意暫存器翻轉的邏輯,第二暫存器是否翻轉取決於第一個暫存器是否為1,前者輸出情況有三種:在data輸入控制為1下從0到1到0不斷翻轉,data為0鎖在1,data為0鎖在0
ps: 考慮rst為1且完成了初始化,rst 低電平復位高電平有效

第三題:

題目連結

奇偶校驗

程式碼

`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
    reg tmp;
    always@(*)begin
        case(sel)
            1'b1:tmp = ^bus;
            1'b0:tmp = ~(^bus);
        endcase
    end
    assign check =tmp;

//*************code***********//
endmodule

題目解析

需要了解什麼是奇偶校驗

奇校驗:對輸入資料新增1位0或者1,使得新增後的數包含奇數個1;

比如100,有奇數個1,那麼奇校驗結果就是0,這樣補完0以後還是奇數個1;

偶校驗:對輸入資料新增1位0或者1,使得新增後的數包含偶數個1;

對bus進行異或,如果有奇數個1,輸出就是1。如果有偶數個1,輸出就是0

這個題目,應該是出題人搞反了,按照出題的意思,應該不能叫奇偶校驗,應該是叫奇偶檢測:

奇檢測:輸入的資料裡有奇數個1就輸出1;

偶檢測:輸入的資料裡有偶數個1就輸出1;

第四題

題目連結

移位運算與乘法

程式碼

`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//

//wire Declaration
wire add_cnt;
wire end_cnt;

//reg Declaration
reg [1:0] cnt;
reg [7:0] tmp;


//計數器
always @(posedge clk or negedge rst)begin
    if(!rst)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign add_cnt = 1 ;     
assign end_cnt = add_cnt && cnt==3 ; 

//輸出訊號
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
        input_grant <=0;
    end
    else if(cnt==0)begin
        input_grant <=1;
    end
    else begin
        input_grant <=0;
    end
end

//資料快取
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
        tmp <= 0;
    end
    else if(cnt==0) begin
         tmp <= d;
    end
end

//訊號輸出
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
        out <= 0;
    end
    else begin
        case(cnt)
            2'b00:out <= d;
            2'b01:out <= (tmp<<1)+tmp;
            2'b10:out <= (tmp<<3)-tmp;
            2'b11:out <= (tmp<<3);
            default:out <=0;
        endcase
    end
end

//*************code***********//
endmodule

題目解析

因為每個時鐘週期分別輸出該數乘1/3/7/8,所以需要一個計數器計算4個週期來輸出資料。輸出訊號在計數器為0時候有效。觀察波形示意圖發現輸出訊號並不是立即跳變而是4個為一個週期來進行跳變,所以需要快取資料。輸出訊號的乘法利用移位來做,可以有效增加時序效能(直接乘綜合出來的加法器含有過多組合邏輯,時序效能很差)

第五題

題目連結

位拆分與運算

程式碼

`timescale 1ns/1ns

module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,

output [4:0]out,
output validout
);
//*************code***********//

//wire declaration

//reg declaration
reg [15:0] tmp;
reg valid;
reg [4:0] signal_out;

//有效訊號
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
        valid <= 0;
    end
    else if(0==sel) begin
        valid <= 0;
    end
    else begin
        valid <= 1;
    end
end

assign validout = valid;

//資料快取
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
         tmp <= 0;
    end
    else if(0==sel) begin
         tmp <= d;
    end
end

//訊號輸出
always  @(posedge clk or negedge rst)begin
    if(rst==1'b0)begin
       signal_out <= 0;
    end
    else begin
        case(sel)
            2'd0: signal_out <= 0;
            2'd1: signal_out <= tmp[3:0] + tmp[7:4];
            2'd2: signal_out <= tmp[3:0] + tmp[11:8];
            2'd3: signal_out <= tmp[3:0] + tmp[15:12];
        endcase
    end
end

assign out =signal_out;

//*************code***********//
endmodule

題目解析

有效訊號是輸出時候,也就是sel不為1的時候是高電平。sel為0的時候是資料輸入,所以快取進來。訊號輸出就是根據題目的意思來就ok了。注意給的都是輸入輸出wire,不能直接在always塊裡面。需要宣告暫存器。

第六題

題目連結

多功能資料處理器

程式碼

`timescale 1ns/1ns
module data_select(
    input clk,
    input rst_n,
    input signed[7:0]a,
    input signed[7:0]b,
    input [1:0]select,
    output reg signed [8:0]c
);

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        c <= 9'd0;
    else case(select)
    2'b00:    c <= a;
    2'b01:    c <= b;
    2'b10:    c <= a+b;
    2'b11:    c <= a-b;
    default: c <= 9'd0;
    endcase

endmodule

題目解析

沒啥解析的地方,多路選擇器,直接根據題意寫就好了。有興趣可以拓展一下有符號數和無符號數的區別

第七題:

題目連結

求兩個數的差值

程式碼

`timescale 1ns/1ns
module data_minus(
    input clk,
    input rst_n,
    input [7:0]a,
    input [7:0]b,

    output  reg [8:0]c
);

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        c <= 0;
    else if(a > b)
        c <= a-b;
    else
        c <= b-a;
endmodule

題目解析

兩個判斷語句輸出就好了

第八題

題目連結

使用generate…for語句簡化程式碼

程式碼

`timescale 1ns/1ns
module gen_for_module(
    input [7:0] data_in,
    output [7:0] data_out
);

    generate
        genvar i;
        for(i = 0; i <8; i=i+1)
            begin:assign_test//名字隨便起,但是必須有
                assign data_out[i] = data_in[7 - i];
            end
    endgenerate

endmodule

題目解析

注意考察generate語句的使用,需要注意兩點,第一個需要genval產生數i,第二個就是for迴圈的begin必須有一個名字。

參考資料

探索者的刷題視訊就很好

FPGA探索者FPGA刷題視訊