日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FPGA秋招面试手撕代码20+

發布時間:2023/12/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FPGA秋招面试手撕代码20+ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
    • 1、序列檢測器
      • (1)三段式狀態機實現方式
      • (2)移位寄存器實現方式
    • 2、序列生成器
      • (1)移位寄存器方式實現
      • (2)計數器方式實現
      • (3)三段式狀態機方式實現
    • 3、分頻
      • (1)偶數分頻
      • (2)奇數分頻
        • ①相與實現
        • ②相或實現
        • ③相異或實現
    • 4、FIFO
      • (1)同步FIFO
        • ①采用地址技術的方式實現
        • ②采用計數器計數的方式實現
      • (2)異步FIFO
    • 5、單比特CDC
      • (1)單比特信號從慢時鐘域->快時鐘域
      • (2)單比特信號從快時鐘域->慢時鐘域
        • ①一般實現方式
        • ②脈沖較近校準(輸出錯誤信息模式)
    • 6、時鐘切換電路
      • (1)使用組合邏輯實現(不推薦)
      • (2)時鐘切換電路(giltch_free同源)
      • (3)時鐘切換電路(giltch_free異步)
    • 7、
      • (1)\
    • 8、
      • (1)\

written by @hzj //版本迭代// # V1.0 2022.7.25 # V1.1 2022.7.27 # V1.2 2022.7.28 # V1.3 2022.8.1 # V1.4 2022.8.3 # V1.5 2022.8.8

前言

針對常用的代碼(常用代碼/面試常考察/基礎代碼)進行手撕訓練,總共的實現代碼總共將近20余個,將在一個月內更新完成,感興趣的朋友可以及時關注下這篇博客,如果有任何的疑問,可以及時與我進行分享。
所有功能模塊為了統一化,都將使用同一個工程名稱“test”,包含src源文件以及tb測試文件,以及可能的RTL圖

廢話不多說,直接進入正題

1、序列檢測器

(1)三段式狀態機實現方式

功能:若檢測序列00110,輸出檢測有效信號signal_en為1

  • SRC:
module test(input i_fpga_clk ,input i_fpga_rst_n ,input data_in ,output reg signal_enable );//define state localparam IDLE = 3'b000; localparam S1 = 3'b001; localparam S2 = 3'b010; localparam S3 = 3'b011; localparam S4 = 3'b100; localparam S5 = 3'b101;//three state reg [2:0] current_state; reg [2:0] next_state ; reg [7:0] count ;always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begincurrent_state <= IDLE;endelse begincurrent_state <= next_state;end endalways @(*) begincase(current_state)IDLE:if(data_in == 1'b0)next_state <= S1;else next_state <= IDLE;S1 :if(data_in == 1'b0)next_state <= S2;else next_state <= IDLE;S2 :if(data_in == 1'b1)next_state <= S3;elsenext_state <= S2;S3 :if(data_in == 1'b1)next_state <= S4;else next_state <= S1;S4 :if(data_in == 1'b0)next_state <= S5;else next_state <= IDLE;S5 :if(data_in == 1'b0)next_state <= S2;else next_state <= IDLE;default:next_state <= IDLE;endcase endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginsignal_enable <= 1'b0;endelse if(current_state == S5)beginsignal_enable <= 1'b1;endelse beginsignal_enable <= 1'b0;end endendmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64;reg clk_368 ; reg rst_n_368 ;initial beginclk_368 <= 'd0 ;rst_n_368 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368; reg data_in; reg [7:0] count; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begindata_in <= 'd0;count <= 8'b00110001;endelse begincount <= {count[6:0], count[7]};data_in <= count[7] ;end endtest module_test(.i_fpga_clk (i_fpga_clk ) ,.i_fpga_rst_n (i_fpga_rst_n ) ,.data_in (data_in ) ,.signal_enable(signal_enable) ); endmodule
  • 仿真結果:

  • 電路:

(2)移位寄存器實現方式

  • SRC:
module test(input i_fpga_clk ,input i_fpga_rst_n ,input data_in ,output reg signal_enable );//00110reg [4:0] data_state;always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begindata_state <= 5'b00000;endelse begindata_state <= {data_state[3:0], data_in};end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginsignal_enable <= 1'b0;endelse if(data_state == 5'b00110)beginsignal_enable <= 1'b1;endelse beginsignal_enable <= 1'b0;end endendmodule
  • TB:
    同1、序列檢測器(三段式狀態機實現方式)的TB代碼

  • 仿真結果:

  • 電路:

2、序列生成器

功能:若檢測序列00110,輸出檢測有效信號signal_en為1

(1)移位寄存器方式實現

  • SRC:
module test(input i_fpga_clk ,input i_fpga_rst_n ,output reg signal_out );reg [4:0] signal_register; always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginsignal_register <= 5'b11010 ; endelse beginsignal_register <= {signal_register[3:0], signal_register[4]};endendalways@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginsignal_out <= 1'b0 ;endelse beginsignal_out <= signal_register[4];end endendmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64;reg clk_368 ; reg rst_n_368 ;initial beginclk_368 <= 'd0 ;rst_n_368 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368;wire signal_out; test module_test(.i_fpga_clk (i_fpga_clk ),.i_fpga_rst_n(i_fpga_rst_n),.signal_out (signal_out ) );endmodule
  • 仿真:

  • 電路:

(2)計數器方式實現

  • SRC:
module test(input i_fpga_clk,input i_fpga_rst_n,output signal_out ); //11010reg [2:0] count; always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)begincount <= 1'b0;endelse if(count == 'd4)begincount <= 'd0;endelse begincount <= count + 1'b1;end endassign signal_out = ((!count[2])&(!count[1])&(!count[0])) | ((!count[2])&(!count[1])&(count[0])) | ((!count[2])&(count[1])&(count[0]));endmodule
  • TB:
    同2(1)

  • 仿真:

  • 電路:

(3)三段式狀態機方式實現

  • SRC:
module test(input i_fpga_clk,input i_fpga_rst_n,output reg signal_out ); localparam IDLE = 3'b000; localparam S1 = 3'b001; localparam S2 = 3'b010; localparam S3 = 3'b011; localparam S4 = 3'b100;reg [2:0] current_state; reg [2:0] next_state ;always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)begincurrent_state <= IDLE;endelse begincurrent_state <= next_state;end endalways@(*)begincase(current_state)IDLE: next_state <= S1;S1 :next_state <= S2;S2 :next_state <= S3;S3 :next_state <= S4;S4 :next_state <= IDLE;default:next_state <= IDLE;endcase endalways@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginsignal_out <= 1'b0; endelse begincase(current_state)IDLE: signal_out <= 1'b1;S1 :signal_out <= 1'b1;S2 :signal_out <= 1'b0;S3 :signal_out <= 1'b1;S4 :signal_out <= 1'b0;default:signal_out <= 1'b0; endcaseend endendmodule
  • TB:
    同2(1)

  • 仿真:

  • 電路:

3、分頻

(1)偶數分頻

功能:實現4分頻電路

  • SRC:
module test(input i_fpga_clk,input i_fpga_rst_n,output reg div );reg [1:0] count; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begincount <= 2'b00;endelse begincount <= count + 2'b01;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begindiv <= 1'b0;endelse if(count == 2'd1 || count == 2'd3)begindiv <= ~div;endelse begindiv <= div;end endendmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64;reg clk_368 ; reg rst_n_368 ;initial beginclk_368 <= 'd0 ;rst_n_368 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368;wire div; test module_test(.i_fpga_clk (i_fpga_clk ),.i_fpga_rst_n(i_fpga_rst_n),.div (div ) );endmodule
  • 仿真:
  • 電路:

(2)奇數分頻

功能:實現奇數分頻的三分頻電路

①相與實現

  • SRC:
module counter(input i_fpga_clk ,input i_fpga_rst_n , output div );reg wave_1; reg wave_2;reg [1:0] count; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)begincount <= 'd0;endelse if(count == 2'd2)begincount <= 'd0;endelse begincount <= count + 1'b1;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_1 <= 1'b0;endelse if(count == 2'd2)beginwave_1 <= 1'b0;endelse beginwave_1 <= 1'b1;end endalways @(negedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_2 <= 'd0;endelse if(count == 2'd2)beginwave_2 <= 1'b0;endelse beginwave_2 <= 1'b1;end endassign div = wave_1 & wave_2;endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_complex_mult;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 end assign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368;wire div ;counter module_counter(.i_fpga_clk (i_fpga_clk ) ,.i_fpga_rst_n(i_fpga_rst_n) , .div (div ) );endmodule
  • 仿真:

  • 電路:

②相或實現

  • SRC:
module counter(input i_fpga_clk ,input i_fpga_rst_n , output div );reg wave_1; reg wave_2;reg [1:0] count; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)begincount <= 'd0;endelse if(count == 2'd2)begincount <= 'd0;endelse begincount <= count + 1'b1;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_1 <= 1'b0;endelse if(count == 2'd0)beginwave_1 <= 1'b1;endelse beginwave_1 <= 1'b0;end endalways @(negedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_2 <= 'd0;endelse if(count == 2'd0)beginwave_2 <= 1'b1;endelse beginwave_2 <= 1'b0;end endassign div = wave_1 | wave_2;endmodule
  • TB:
    同4(1)

  • 仿真:

  • 電路:

③相異或實現

  • SRC:
module counter(input i_fpga_clk ,input i_fpga_rst_n , output div );reg wave_1; reg wave_2;reg [1:0] count; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)begincount <= 'd0;endelse if(count == 2'd2)begincount <= 'd0;endelse begincount <= count + 1'b1;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_1 <= 1'b0;endelse if(count == 2'd0)beginwave_1 <= ~wave_1;endelse beginwave_1 <= wave_1;end endalways @(negedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'd0)beginwave_2 <= 'd0;endelse if(count == 2'd2)beginwave_2 <= ~wave_2;endelse beginwave_2 <= wave_2;end endassign div = wave_1 ^ wave_2;endmodule
  • TB:
    同4(1)

  • 仿真:

  • 電路:

4、FIFO

(1)同步FIFO

*功能:實現深度大小為8,位寬大小為32的同步FIFO*

①采用地址技術的方式實現

  • SRC:
module test#(parameter DATA_DEPTH = 16,parameter DATA_WIDTH = 16 )(input i_fpga_clk ,input i_fpga_rst_n , input wr_en ,input [DATA_WIDTH-1:0] wr_data ,input rd_en ,output reg [DATA_DEPTH-1:0] rd_data ,output full_signal ,output empty_signal );reg [DATA_WIDTH-1:0] memory [DATA_DEPTH-1:0];//定義一個數組元素用作存儲function integer c2log(input [DATA_DEPTH-1:0] data_depth); beginfor(c2log = 0; data_depth > 0 ;c2log = c2log + 1)begindata_depth = data_depth >> 1;end end endfunctionreg [c2log(DATA_DEPTH - 1)-1 :0] wr_addr; reg [c2log(DATA_DEPTH - 1)-1 :0] rd_addr;//wr_addr always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginwr_addr <= 'd0;endelse if(wr_en == 1'b1 && full_signal != 1'b1)beginwr_addr <= wr_addr + 1'b1;endelse beginwr_addr <= wr_addr;end end//rd_addr always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginrd_addr <= 'd0;endelse if(rd_en == 1'b1 && empty_signal != 1'b1)beginrd_addr <= rd_addr + 1'b1;endelse beginrd_addr <= rd_addr;end end//mem_wr always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginmemory[wr_addr] <= 'd0;endelse if(wr_en == 1'b1 && full_signal != 1'b1)beginmemory[wr_addr] <= wr_data;endelse beginmemory[wr_addr] <= memory[wr_addr];end end//mem_rd always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginrd_data <= 'd0;endelse if(rd_en == 1'b1 && empty_signal != 1'b1)beginrd_data <= memory[rd_addr];endelse beginrd_data <= rd_data;end end//judege_empty_full assign empty_signal = (wr_addr == rd_addr )? 1'd1: 1'd0; assign full_signal = ((wr_addr[2:0]== rd_addr[2:0])&&(wr_addr[3] != rd_addr[3]))? 1'd1: 1'd0;endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368;reg wr_en; reg rd_en; reg [15:0] wr_data; reg [4:0 ] counter; reg flag; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begincounter <= 'd0;wr_en <= 'd0;rd_en <= 'd0;flag <= 'd0;endelse if(counter == 'd7 && flag == 'd0)beginflag <= 'd1;wr_en <= 'd1;endelse if(counter == 'd7 && flag == 'd1)begincounter <= 'd0;wr_en <= ~wr_en;rd_en <= ~rd_en;endelse begincounter <= counter + 1'b1;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginwr_data <= 'd0;endelse if(wr_data == 'd20)beginwr_data <= 'd0;endelse beginwr_data <= wr_data + 1;end endwire [15:0]rd_data;test#(.DATA_DEPTH(16),.DATA_WIDTH(16) )module_test(.i_fpga_clk (i_fpga_clk ),.i_fpga_rst_n (i_fpga_rst_n), .wr_en (wr_en ),.wr_data (wr_data ),.rd_en (rd_en ),.rd_data (rd_data ),.full_signal (full_signal ),.empty_signal (empty_signal) ); endmodule
  • 仿真:

  • 電路:

②采用計數器計數的方式實現

  • SRC:
module test#(parameter DATA_WIDTH = 16,parameter DATA_DEPTH = 8 )( //sync_fifoinput i_fpga_clk ,input i_fpga_rst_n ,input [DATA_WIDTH - 1 : 0] wr_data ,input wr_en ,output reg [DATA_WIDTH -1 : 0] rd_data ,input rd_en ,output full_signal ,output empty_signal);//calculate the DEPTH bitsfunction integer c2log(input [DATA_DEPTH - 1: 0] data_depth);beginfor(c2log = 0; data_depth >0 ; c2log = c2log + 1)begindata_depth = data_depth >> 1; endendendfunction//define the dignalreg [c2log(DATA_DEPTH-1) - 1 : 0] wr_addr ;reg [c2log(DATA_DEPTH-1) - 1 : 0] rd_addr ;reg [DATA_WIDTH - 1 : 0] mem [DATA_DEPTH-1 : 0];//wr_addralways@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginwr_addr <= 16'd0;endelse if(wr_en == 1'b1 && full_signal == 1'b0)beginwr_addr <= wr_addr + 1'b1;endend//rd_addralways@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginrd_addr <= 16'b0;endelse if(empty_signal == 1'b0 && rd_en == 1'b1)beginrd_addr <= rd_addr + 1'b1;endend//wr_datainteger bit_width;always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginfor(bit_width = 0; bit_width < DATA_DEPTH; bit_width = bit_width + 1)beginmem[bit_width] <= 32'd0;endendelse if(wr_en == 1'b1 && full_signal == 1'b0)beginmem[wr_addr] <= wr_data;endend//rd_dataalways@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)beginrd_data <= 'd0;endelse if(rd_en == 1'b1 && empty_signal == 1'b0)beginrd_data <= mem[rd_addr];endend//countreg [3:0] count;always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)begincount <= 'd0; endelse if(wr_en == 1'b1 && full_signal == 1'b0)begincount <= count + 1'b1;endelse if(rd_en == 1'b1 && empty_signal == 1'b0)begincount <= count - 1'b1;endelse begincount <= count;endendassign full_signal = (count == 'd8 ? 1 : 0);assign empty_signal = (count == 'd0 ? 1 : 0); endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368;reg wr_en; reg rd_en; reg [15:0] wr_data; reg [4:0 ] counter; reg flag; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begincounter <= 'd0;wr_en <= 'd0;rd_en <= 'd0;flag <= 'd0;endelse if(counter == 'd7 && flag == 'd0)beginflag <= 'd1;wr_en <= 'd1;endelse if(counter == 'd7 && flag == 'd1)begincounter <= 'd0;wr_en <= ~wr_en;rd_en <= ~rd_en;endelse begincounter <= counter + 1'b1;end endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginwr_data <= 'd0;endelse if(wr_data == 'd20)beginwr_data <= 'd0;endelse beginwr_data <= wr_data + 1;end endwire [15:0]rd_data;test#(.DATA_WIDTH(16),.DATA_DEPTH( 8) )module_test( //sync_fifo.i_fpga_clk (i_fpga_clk ),.i_fpga_rst_n (i_fpga_rst_n),.wr_data (wr_data ),.wr_en (wr_en ),.rd_data (rd_data ),.rd_en (rd_en ),.full_signal (full_signal ),.empty_signal (empty_signal));endmodule
  • 仿真:
  • 電路:

(2)異步FIFO

功能:實現異步FIFO功能,具備gray碼

  • SRC:
module test#(parameter DATA_WIDTH = 16,parameter DATA_DEPTH = 8 )( //sync_fifoinput i_fpga_clk_wr ,input i_fpga_rst_n_wr ,input i_fpga_clk_rd ,input i_fpga_rst_n_rd ,input [DATA_WIDTH - 1 : 0] wr_data ,input wr_en ,output reg [DATA_WIDTH -1 : 0] rd_data ,input rd_en ,output full_signal ,output empty_signal);//calculate the DEPTH bitsfunction integer c2log(input [DATA_DEPTH - 1: 0] data_depth);beginfor(c2log = 0; data_depth >0 ; c2log = c2log + 1)begindata_depth = data_depth >> 1; endendendfunction//define the dignalreg [c2log(DATA_DEPTH-1) : 0] wr_ptr ;wire[c2log(DATA_DEPTH-1) : 0] gray_wr_ptr_0 ;reg [c2log(DATA_DEPTH-1) : 0] gray_wr_ptr_1 ;reg [c2log(DATA_DEPTH-1) : 0] gray_wr_ptr_2 ;reg [c2log(DATA_DEPTH-1) : 0] rd_ptr ;wire[c2log(DATA_DEPTH-1) : 0] gray_rd_ptr_0 ;reg [c2log(DATA_DEPTH-1) : 0] gray_rd_ptr_1 ;reg [c2log(DATA_DEPTH-1) : 0] gray_rd_ptr_2 ;reg [DATA_WIDTH - 1 : 0] mem [DATA_DEPTH-1 : 0];//wr dataalways @(posedge i_fpga_clk_wr or negedge i_fpga_rst_n_wr)beginif(i_fpga_rst_n_wr == 1'b0)beginwr_ptr <= {(c2log(DATA_DEPTH)){1'b0}};endelse if(wr_en == 1'b1 && full_signal == 1'b0)beginwr_ptr <= wr_ptr + 1'b1;endend//rd c2log always@(posedge i_fpga_clk_rd or negedge i_fpga_rst_n_rd)beginif(i_fpga_rst_n_rd == 1'b0)beginrd_ptr <= {(c2log(DATA_DEPTH-1)){1'b0}};endelse if(rd_en == 1'b1 && empty_signal == 1'b0)beginrd_ptr <= rd_ptr + 1'b1;end end//gray generate assign gray_wr_ptr_0 = wr_ptr ^ (wr_ptr >> 1); assign gray_rd_ptr_0 = rd_ptr ^ (rd_ptr >> 1);//CDC sync wr always@(posedge i_fpga_clk_rd or negedge i_fpga_rst_n_rd)beginif(i_fpga_rst_n_rd == 1'b0)begingray_wr_ptr_1 <= {(c2log(DATA_DEPTH-1)){1'b0}};gray_wr_ptr_2 <= {(c2log(DATA_DEPTH-1)){1'b0}};endelse begingray_wr_ptr_1 <= gray_wr_ptr_0;gray_wr_ptr_2 <= gray_wr_ptr_1;end end//CDC sync rd always@(posedge i_fpga_clk_wr or negedge i_fpga_rst_n_wr)beginif(i_fpga_rst_n_wr == 1'b0)begingray_rd_ptr_1 <= {(c2log(DATA_DEPTH-1)){1'b0}};gray_rd_ptr_2 <= {(c2log(DATA_DEPTH-1)){1'b0}};endelse begingray_rd_ptr_1 <= gray_rd_ptr_0;gray_rd_ptr_2 <= gray_rd_ptr_1;end end//full_signal && empty signal assign full_signal = (gray_wr_ptr_0 == {~gray_rd_ptr_2[c2log(DATA_DEPTH-1) : c2log(DATA_DEPTH-1) - 1], gray_rd_ptr_2[c2log(DATA_DEPTH-1)-2 : 0]} ? 1 : 0 ); assign empty_signal= (gray_rd_ptr_0 == gray_wr_ptr_2);//addr generate wire [c2log(DATA_DEPTH - 1) - 1 : 0]wr_addr; wire [c2log(DATA_DEPTH - 1) - 1 : 0]rd_addr; assign wr_addr = wr_ptr [c2log(DATA_DEPTH - 1) - 1 : 0]; assign rd_addr = rd_ptr [c2log(DATA_DEPTH - 1) - 1 : 0];//wr_data integer i;always@(posedge i_fpga_clk_wr or negedge i_fpga_rst_n_wr)beginif(i_fpga_rst_n_wr == 1'b0)beginfor(i = 0 ; i < DATA_DEPTH ; i = i + 1)beginmem[i] <= {DATA_DEPTH{1'b0}};endendelse if(wr_en == 1'b1 && full_signal == 1'b0)beginmem[wr_addr] <= wr_data;end end//rd_data always@(posedge i_fpga_clk_rd or negedge i_fpga_rst_n_rd)beginif(i_fpga_rst_n_rd == 1'b0)beginrd_data <= {DATA_WIDTH{1'b0}};endelse if(rd_en == 1'b1 && empty_signal == 1'b0)beginrd_data <= mem[rd_addr];end endendmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endinitial beginforever #(PERIOD_245P76/2) clk_245 =~clk_245; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368; assign i_fpga_clk_wr = clk_368 ; assign i_fpga_rst_n_wr = rst_n_368; assign i_fpga_clk_rd = clk_245; assign i_fpga_rst_n_rd = rst_n_245;reg wr_en; reg rd_en; reg [15:0] wr_data; reg [4:0 ] counter; reg flag; always @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)begincounter <= 'd0;wr_en <= 'd0;flag <= 'd0;endelse if(counter == 'd7 && flag == 'd0)beginflag <= 'd1;wr_en <= 'd1;endelse if(counter == 'd7 && flag == 'd1)begin//counter <= 'd0;wr_en <= ~wr_en;endelse if(counter == 'd15)begincounter <= 'd0;endelse begincounter <= counter + 1'b1;end end//reg flag_rd; //reg [4:0] count_rd; //always @(posedge i_fpga_clk_rd or negedge i_fpga_rst_n_rd begin // if(i_fpga_rst_n_rd == 1'b0)begin // rd_en <= 'd0; // flag_rd<= 'd0; // end // else if(count_rd == 'd && flag_rd== 'd0)begin // flag_rd<= 'd1; // end // else if(count_rd == 'd7 && flag_rd== 'd1)begin // rd_en <= ~rd_en; // end //endalways @(posedge i_fpga_clk or negedge i_fpga_rst_n) beginif(i_fpga_rst_n == 1'b0)beginwr_data <= 'd0;endelse if(wr_data == 'd20)beginwr_data <= 'd0;endelse beginwr_data <= wr_data + 1;end endwire [15:0]rd_data;reg [8:0]count_time; always@(posedge i_fpga_clk_rd or negedge i_fpga_rst_n_rd)begin if(i_fpga_rst_n_rd == 1'b0)begincount_time <= 'd0;rd_en <= 'd1;endelse if(count_time == 'd100)beginrd_en <= 'd0;endelse begin count_time <= count_time + 1'b1;rd_en <= rd_en;end endtest#(.DATA_WIDTH(16),.DATA_DEPTH( 8) )test( //sync_fifo.i_fpga_clk_wr (i_fpga_clk_wr ) ,.i_fpga_rst_n_wr (i_fpga_rst_n_wr ) ,.i_fpga_clk_rd (i_fpga_clk_rd ) ,.i_fpga_rst_n_rd (i_fpga_rst_n_rd ) ,.wr_data (wr_data ) ,.wr_en (wr_en ) ,.rd_data (rd_data) ,.rd_en (rd_en ) ,.full_signal (full_signal ) ,.empty_signal(empty_signal)); endmodule
  • 仿真:

  • 電路:

5、單比特CDC

(1)單比特信號從慢時鐘域->快時鐘域

功能:單比特信號CDC(采用打兩拍實現)

  • SRC:
module test(input i_fpga_clk_src ,//slowinput i_fpga_rst_n_src ,input i_fpga_clk_des ,//fastinput i_fpga_rst_n_des ,input i_pulse_in ,output o_pulse_out );reg r_pluse_r1; reg r_pluse_r2;always @(posedge i_fpga_clk_des or negedge i_fpga_rst_n_des) beginif(i_fpga_rst_n_des == 1'b0)beginr_pluse_r1 <= 1'b0;r_pluse_r2 <= 1'b0;endelse beginr_pluse_r1 <= i_pulse_in;r_pluse_r2 <= r_pluse_r1;end endassign o_pulse_out = r_pluse_r2;endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endinitial beginforever #(PERIOD_245P76/2) clk_245 =~clk_245; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368; assign i_fpga_clk_rd = clk_368 ; assign i_fpga_rst_n_rd = rst_n_368; assign i_fpga_clk_wr = clk_245; assign i_fpga_rst_n_wr = rst_n_245;reg wr_en; reg rd_en; reg [15:0] wr_data; reg [4:0 ] counter; reg flag;always@(posedge i_fpga_clk_wr or negedge i_fpga_rst_n_wr)beginif(i_fpga_rst_n == 1'b0)begincounter <= 'd0;wr_en <= 1'b0;endelse if(counter == 'd7 | counter == 'd8)beginwr_en <= 1'b1;counter <= counter + 1'b1;endelse begin wr_en <= 1'b0;counter <= counter + 1'b1;end end wire o_pulse_out;test module_test(.i_fpga_clk_src (i_fpga_clk_wr ),.i_fpga_rst_n_src(i_fpga_rst_n_wr),.i_fpga_clk_des (i_fpga_clk_rd ),.i_fpga_rst_n_des(i_fpga_rst_n_rd),.i_pulse_in (wr_en ),.o_pulse_out (o_pulse_out) );endmodule
  • 仿真:

  • 電路:

(2)單比特信號從快時鐘域->慢時鐘域

功能:單位脈沖信號單比特信號從快時鐘域->慢時鐘域CDC

①一般實現方式

  • SRC:
module test(input i_fpga_clk_src ,input i_fpga_rst_n_src ,input i_fpga_clk_des ,input i_fpga_rst_n_des ,input i_pulse_in ,output o_pulse_out ); //define reg reg req_signal; reg req_signal_r1; reg req_signal_r2;reg ack_signal; reg ack_signal_r1; reg ack_signal_r2;//req mamaegementalways@(posedge i_fpga_clk_src or negedge i_fpga_rst_n_src)beginif(i_fpga_rst_n_src == 1'b0)beginreq_signal <= 1'b0;endelse if(i_pulse_in == 1'b1)beginreq_signal <= 1'b1;endelse if(ack_signal_r2 == 1'b1)beginreq_signal <= 1'b0;endelse beginreq_signal <= req_signal;end end//CDC req_signal always@(posedge i_fpga_clk_des or negedge i_fpga_rst_n_des)beginif(i_fpga_rst_n_des == 1'b0)beginreq_signal_r1 <= 1'b0;req_signal_r2 <= 1'b0;endelse beginreq_signal_r1 <= req_signal ;req_signal_r2 <= req_signal_r1;ack_signal <= req_signal_r2;end end//CDC ack_signal always@(posedge i_fpga_clk_src or negedge i_fpga_rst_n_src)beginif(i_fpga_rst_n_src == 1'b0)beginack_signal_r1 <= 1'b0;ack_signal_r2 <= 1'b0;endelse beginack_signal_r1 <= ack_signal ;ack_signal_r2 <= ack_signal_r1;end end//output signal generate assign o_pulse_out = req_signal_r2 & ~ack_signal;endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; integer i; integer j;initial begini <= 0;j <= 0;clk_368 <= 'd0 ;rst_n_368 <= 'd0 ;clk_245 <= 'd0 ;rst_n_245 <= 'd0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; endinitial beginforever #(PERIOD_368P64/2) clk_368 =~clk_368; //clk_368的周期 endinitial beginforever #(PERIOD_245P76/2) clk_245 =~clk_245; //clk_368的周期 endassign i_fpga_clk = clk_368 ; assign i_fpga_rst_n = rst_n_368; assign i_fpga_clk_wr = clk_368 ; assign i_fpga_rst_n_wr = rst_n_368; assign i_fpga_clk_rd = clk_245; assign i_fpga_rst_n_rd = rst_n_245;reg wr_en; reg rd_en; reg [15:0] wr_data; reg [4:0 ] counter; reg flag;always@(posedge i_fpga_clk or negedge i_fpga_rst_n)beginif(i_fpga_rst_n == 1'b0)begincounter <= 'd0;wr_en <= 1'b0;endelse if(counter == 'd7 | counter == 'd8)beginwr_en <= 1'b1;counter <= counter + 1'b1;endelse begin wr_en <= 1'b0;counter <= counter + 1'b1;end endtest module_test(.i_fpga_clk_src (i_fpga_clk_wr ),.i_fpga_rst_n_src(i_fpga_rst_n_wr),.i_fpga_clk_des (i_fpga_clk_rd ),.i_fpga_rst_n_des(i_fpga_rst_n_rd),.i_pulse_in (wr_en) ,. o_pulse_out () );endmodule
  • 仿真:
  • 電路:

②脈沖較近校準(輸出錯誤信息模式)

可以校準相鄰較近的脈沖信號,若相鄰太近輸入,那么將會輸出error

  • SRC:
module test(input i_fpga_clk_src ,input i_fpga_rst_n_src ,input i_fpga_clk_des ,input i_fpga_rst_n_des ,input i_pulse_in ,output o_pulse_out ); //define reg reg req_signal; reg req_signal_r1; reg req_signal_r2;reg ack_signal; reg ack_signal_r1; reg ack_signal_r2;wire idle_state;reg error_state; //idle_state setting assign idle_state = ~(req_signal | req_signal_r2);//error state detect always@(posedge i_fpga_clk_src or negedge i_fpga_rst_n_src)beginif(i_fpga_rst_n_src == 1'b0)beginerror_state <= 1'b0;endelse if(idle_state == 1'b1 & i_pulse_in == 1'b1)beginerror_state <= 1'b1;endelse beginerror_state <= 1'b0;end end//req mamaegementalways@(posedge i_fpga_clk_src or negedge i_fpga_rst_n_src)beginif(i_fpga_rst_n_src == 1'b0)beginreq_signal <= 1'b0;endelse if(i_pulse_in == 1'b1 && idle_state == 1'b1)beginreq_signal <= 1'b1;endelse if(ack_signal_r2 == 1'b1)beginreq_signal <= 1'b0;endelse beginreq_signal <= req_signal;end end//CDC req_signal always@(posedge i_fpga_clk_des or negedge i_fpga_rst_n_des)beginif(i_fpga_rst_n_des == 1'b0)beginreq_signal_r1 <= 1'b0;req_signal_r2 <= 1'b0;ack_signal <= 1'b0;endelse beginreq_signal_r1 <= req_signal ;req_signal_r2 <= req_signal_r1;ack_signal <= req_signal_r2;end end//CDC ack_signal always@(posedge i_fpga_clk_src or negedge i_fpga_rst_n_src)beginif(i_fpga_rst_n_src == 1'b0)beginack_signal_r1 <= 1'b0;ack_signal_r2 <= 1'b0;endelse beginack_signal_r1 <= ack_signal ;ack_signal_r2 <= ack_signal_r1;end end//output signal generate assign o_pulse_out = ack_signal_r1 & ~ack_signal_r2;endmodule
  • TB:
    同7(1)

  • 仿真:

  • 電路:

6、時鐘切換電路

功能:實現不同時鐘的切換

(1)使用組合邏輯實現(不推薦)

有很多毛刺,后級時鐘信號不安全,無法直接使用

  • SRC:
module test(input i_fpga_clk_frq1 ,input i_fpga_clk_frq2 ,input i_seletion ,input i_fpga_rst ,output o_fpga_clk );assign o_fpga_clk = i_seletion ? i_fpga_clk_frq1 : i_fpga_clk_frq2;//no suggest to use endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_368P64 = 1000/368.64; parameter PERIOD_245P76 = 1000/245.76;//define reg clk_368 ; reg clk_245; reg rst_n_368 ; reg rst_n_245 ; reg selection ;//initial initial beginclk_245 = 0 ;clk_368 = 0 ;rst_n_245 = 0 ;rst_n_368 = 0 ;selection = 0 ;repeat(10) @ (posedge clk_368);selection = 1 ;repeat(30) @ (posedge clk_368);selection = 0 ; endinitial begin#(PERIOD_368P64) rst_n_368 = 1'b1; endinitial begin#(PERIOD_245P76) rst_n_245 = 1'b1; end//clk generatealways #(PERIOD_368P64) clk_368 = ~clk_368;always #(PERIOD_245P76) clk_245 = ~clk_245;//module wire o_fpga_clk;test tb_test(.i_fpga_clk_frq1(clk_368 ),.i_fpga_clk_frq2(clk_245 ),.i_seletion (selection),.i_fpga_rst (rst_n_368),.o_fpga_clk (o_fpga_clk) );endmodule
  • 仿真:

  • 電路:

(2)時鐘切換電路(giltch_free同源)

  • SRC:
module test(input i_fpga_clk_frq1 ,input i_fpga_clk_frq2 ,input i_seletion ,input i_fpga_rst ,output o_fpga_clk );//definereg enable_1;reg enable_2;//domain 1always @(negedge i_fpga_clk_frq1 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_1 <= 1'b0;endelse beginenable_1 <= (~enable_2) & i_seletion;endend//domain 2always @(negedge i_fpga_clk_frq2 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_2 <= 1'b0;endelse beginenable_2 <= (~enable_1) & (~i_seletion);endend//generate assign o_fpga_clk = (enable_1 & i_fpga_clk_frq1) | (enable_2 & i_fpga_clk_frq2);endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_400 = 4000/400; parameter PERIOD_200 = 4000/200;//define reg clk_400 ; reg clk_200; reg rst_n_400 ; reg rst_n_200 ; reg selection ;//initial initial beginclk_200 = 0 ;clk_400 = 0 ;rst_n_200 = 0 ;rst_n_400 = 0 ;selection = 0 ;repeat(10) @ (posedge clk_400);selection = 1 ;repeat(30) @ (posedge clk_400);selection = 0 ; endinitial begin#(PERIOD_400) rst_n_400 = 1'b1; endinitial begin#(PERIOD_200) rst_n_200 = 1'b1; end//clk generatealways #(PERIOD_400) clk_400 = ~clk_400;always #(PERIOD_200) clk_200 = ~clk_200;//module wire o_fpga_clk;test tb_test(.i_fpga_clk_frq1(clk_400 ),.i_fpga_clk_frq2(clk_200 ),.i_seletion (selection),.i_fpga_rst (rst_n_400),.o_fpga_clk (o_fpga_clk) );endmodule
  • 仿真:

  • 電路:

(3)時鐘切換電路(giltch_free異步)

  • SRC:
module test(input i_fpga_clk_frq1 ,input i_fpga_clk_frq2 ,input i_selection ,input i_fpga_rst ,output o_fpga_clk );//definereg enable_1 ;reg enable_1_r;reg enable_2 ;reg enable_2_r;//domain 1always @(posedge i_fpga_clk_frq1 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_1 <= 1'b0;endelse beginenable_1 <= (~enable_2_r) & i_selection ;endendalways @(negedge i_fpga_clk_frq1 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_1_r <= 1'b0 ;endelse beginenable_1_r <= enable_1 ;endend//domain 2always @(posedge i_fpga_clk_frq2 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_2 <= 1'b0;endelse beginenable_2 <= (~enable_1_r) & (~i_selection);endendalways @(negedge i_fpga_clk_frq2 or negedge i_fpga_rst) beginif(i_fpga_rst == 1'b0)beginenable_2_r <= 1'b0 ;endelse beginenable_2_r <= enable_2 ;endend//generate assign o_fpga_clk = (enable_1_r & i_fpga_clk_frq1) | (enable_2_r & i_fpga_clk_frq2);endmodule
  • TB:
`timescale 1ns / 1ps //1000Mmodule tb_test;parameter PERIOD_400 = 4000/399; parameter PERIOD_200 = 4000/200;//define reg clk_400 ; reg clk_200; reg rst_n_400 ; reg rst_n_200 ; reg selection ;//initial initial beginclk_200 = 0 ;clk_400 = 0 ;rst_n_200 = 0 ;rst_n_400 = 0 ;selection = 0 ;repeat(10) @ (posedge clk_400);selection = 1 ;repeat(30) @ (posedge clk_400);selection = 0 ; endinitial begin#(PERIOD_400) rst_n_400 = 1'b1; endinitial begin#(PERIOD_200) rst_n_200 = 1'b1; end//clk generatealways #(PERIOD_400) clk_400 = ~clk_400;always #(PERIOD_200) clk_200 = ~clk_200;//module wire o_fpga_clk;test tb_test(.i_fpga_clk_frq1(clk_400 ),.i_fpga_clk_frq2(clk_200 ),.i_selection (selection),.i_fpga_rst (rst_n_400),.o_fpga_clk (o_fpga_clk) );endmodule
  • 仿真:

  • 電路:

7、

功能:

(1)\

  • SRC:
  • TB:
  • 仿真:
  • 電路:

8、

功能:

(1)\

  • SRC:
  • TB:
  • 仿真:
  • 電路:

總結

以上是生活随笔為你收集整理的FPGA秋招面试手撕代码20+的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。