天天看點

數字IC手撕代碼-握手信号(READY-VALID)握手信号接口解釋代碼testbench 

 前言:

        本專欄旨在記錄高頻筆面試手撕代碼題,以備數字前端秋招,本專欄所有文章提供原理分析、代碼及波形,所有代碼均經過本人驗證。

目錄如下:

1.數字IC手撕代碼-分頻器(任意偶數分頻)

2.數字IC手撕代碼-分頻器(任意奇數分頻)

3.數字IC手撕代碼-分頻器(任意小數分頻)

4.數字IC手撕代碼-異步複位同步釋放

5.數字IC手撕代碼-邊沿檢測(上升沿、下降沿、雙邊沿)

6.數字IC手撕代碼-序列檢測(狀态機寫法)

7.數字IC手撕代碼-序列檢測(移位寄存器寫法)

8.數字IC手撕代碼-半加器、全加器

9.數字IC手撕代碼-串轉并、并轉串

10.數字IC手撕代碼-資料位寬轉換器(寬-窄,窄-寬轉換)

11.數字IC手撕代碼-有限狀态機FSM-飲料機

12.數字IC手撕代碼-握手信号(READY-VALID)

13.數字IC手撕代碼-流水握手(利用握手解決流水線斷流、反壓問題)

14.數字IC手撕代碼-泰淩微筆試真題

15.數字IC手撕代碼-平頭哥技術終面手撕真題

16.數字IC手撕代碼-兆易創新筆試真題

17.數字IC手撕代碼-樂鑫科技筆試真題(4倍頻)

18.數字IC手撕代碼-雙端口RAM(dual-port-RAM)

        ...持續更新

為了友善可以收藏導覽部落格: 數字IC手撕代碼-導覽目錄

目錄

握手信号

接口解釋

代碼

testbench 

波形

握手信号

握手信号,就是為了子產品之間的資料互動正确才衍生出來的信号。其無非就是三種可能

        一、上遊master提供的valid 信号随資料一起拉高,但下遊slave過一段時間才準備好的valid先高為敬。 

數字IC手撕代碼-握手信号(READY-VALID)握手信号接口解釋代碼testbench 

        二、下遊slave一直準備好,但上遊資料過段時間才有效的ready先高為敬。

數字IC手撕代碼-握手信号(READY-VALID)握手信号接口解釋代碼testbench 

        三、上遊master的valid信号和下遊slave的ready同時為高。 

數字IC手撕代碼-握手信号(READY-VALID)握手信号接口解釋代碼testbench 

        當我第一次接觸握手信号的時候,其實是很清楚上面的三條握手原則的,但是具體的,master和slave之間的握手信号該怎麼寫代碼卻迷迷糊糊。就利用這篇文章簡單的講一下master和slave之間是怎麼通過握手信号來解決資料互動問題的。同時也為下一篇文章《多級流水線握手》打下基礎。下一篇文章會講解如何利用握手信号,解決流水線因為上流斷流及下遊反壓導緻的流水線停滞問題。

        好,回到本篇文章來。

        對于master來說,master發出一個資料,如果資料有效,master就會把傳送給slave的valid信号拉高,即告訴slave資料有效可以接收!如果slave準備好了,slave就把傳送給master的ready信号拉高,告訴master我準備好了,如果你資料有效,我就可以接收!是以當master傳輸的資料有效,且slave也準備好時,資料就會在下一個周期被slave取走,master可以接着傳下一個資料。

接口解釋

        對于你寫的子產品來說,如果要跟上下做資料握手,那麼對于上遊,你是一個slave,對于下遊,你又是一個master了,是以接口應該如下:

module handshake(
  input         clk       ,
  input         rstn      ,

  input [7:0]   data_i    ,
  input         valid_i   ,
  input         ready_o   ,

  output [7:0]  data_o    ,
  input         ready_i   ,
  output        valid_o
);

           

        data_i為輸入的資料,如果valid_i為1,則資料有效,ready_o是slave發送給上遊master的準備信号,如果ready_o準備好了,則為1。

        data_o為該子產品輸出給下遊的資料,如果輸出的資料有效,則valid_o為1。下遊也會有準備好和沒準備好的時候,是以還需要一個下遊提供給本子產品的ready_i信号,來告訴我們下遊是否準備完畢。 

代碼

module handshake(
  input         clk       ,
  input         rstn      ,

  input [7:0]   data_i    ,
  input         valid_i   ,
  output        ready_o   ,

  output [7:0]  data_o    ,
  input         ready_i   ,
  output        valid_o
);

reg [7:0] data_o_r;
reg valid_o_r;

assign ready_o = ready_i;     //如果下遊準備好了,那我就準備好了

always @(posedge clk)begin
  if(ready_i && valid_i)begin //如果下遊準備好了,并且上遊資料有效,那就把輸入的資料乘以二輸出
    data_o_r <= data_i * 2;   
  end
end

always @(posedge clk)begin
  if(!rstn)begin
    valid_o_r <= 1'b0;
  end
  else if(ready_o)begin
    valid_o_r <= valid_i;     //如果我準備好了,我就把上遊的valid傳遞給下遊。
  end
end

assign data_o  = data_o_r;
assign valid_o = valid_o_r;

endmodule
           

代碼編寫如上,關鍵就在于注釋:

        1.如果下遊準備好了,并且上遊輸入的資料有效的話, 把輸入資料乘以二指派給輸出資料。

        2.如果下遊準備好可以接收資料了,那本子產品就可以處理資料了。

        3.如果本子產品準備好了,就把上遊的valid_i傳遞給下遊valid_o.

這裡的testbench也很重要。

testbench 

module handshake_tb();

reg clk,rstn;

always #5 clk = ~clk;

reg valid_i,ready_i;
wire ready_o,valid_o;

reg  [7:0] data_i;
wire [7:0] data_o;

initial begin
  clk   <= 1'b0;
  rstn  <= 1'b0;
  #25
  rstn    <= 1'b1;
  ready_i <= 1'b1;    //下遊準備好了
  valid_i <= 1'b0;    //上遊資料無效
  data_i  <= 8'b0000_1000;
  #10
  data_i  <= 8'b0111_1000;
  valid_i <= 1'b1;    //上遊資料有效
  #10
  data_i  <= 8'b0100_0100;
  #10
  valid_i <= 1'b0;
  #10
  data_i  <= 8'b0010_0100;
  valid_i <= 1'b1;    //雖然上遊資料有效,但下遊沒準備好
  ready_i <= 1'b0;
  #20
  ready_i <= 1'b1;    //上遊資料有效,下遊準備好了
  #10
  valid_i <= 1'b0;
  #500
  $stop();
end

handshake u_handshake(
  .clk      (clk)     ,
  .rstn     (rstn)    ,
  .data_i   (data_i)  ,
  .data_o   (data_o)  ,

  .ready_i  (ready_i) ,
  .ready_o  (ready_o) ,
  .valid_i  (valid_i) ,
  .valid_o  (valid_o)

);

endmodule
           

        我們用tb來模拟本子產品的上遊master和下遊slave,用tb給本子產品提供上遊資料data_i和valid_i信号。分别模拟了上遊斷流,即valid_i中途拉低,以及下遊反壓,即ready_i中途為低的情況。都通過。 

波形

數字IC手撕代碼-握手信号(READY-VALID)握手信号接口解釋代碼testbench 

        當輸出資料有效的時候,本子產品輸出的valid_o為高,均符合要求。不熟悉的小夥伴,多看看波形了解一下,整個module也在上面分為兩部分貼出來了,感興趣可以自己動手打一下,上面的是完整代碼。tb省略了端口例化和變量定義。 

繼續閱讀