牛客網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變數即可
第二題
題目連結
程式碼
`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
題目解析
兩個判斷語句輸出就好了
第八題
題目連結
程式碼
`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必須有一個名字。
參考資料
探索者的刷題視訊就很好