「一種解決匯流排同步問題的方法是使用乙個保持暫存器和握手訊號」,這也就是「先非同步暫存,後同步寫入」的方法
分別編寫了傳送時鐘域和接收時鐘域的**進行測試,用到兩組mem,以便於觀察實驗結果:
//傳送端**
//接收域應答訊號ack採用兩級暫存器同步,便於時序收斂
module woshou_tx
( input rst_n,
input t_clk,
input ack,
output [7:
0] dout,
output reg req);
reg ack_reg1,ack_reg2;
reg [7:
0] data_buf;
reg [2:
0]tr_state;
reg [7:
0] tr_mem_addr;
reg [7:
0] tr_mem [
255:0]
;parameter tr_idle=
3'b000, snd_data_req=3'b001, chk_ack_active=
3'b010, chk_comm_end=3'b100;
always@(negedge rst_n or posedge t_clk)
begin
if(!rst_n)begin
ack_reg1 <=
1'b0;
ack_reg2 <=
1'b0;
endelse begin
ack_reg1 <= ack;
ack_reg2 <= ack_reg1;
endend//
always@(posedge t_clk or negedge rst_n)
begin
if(!rst_n)
begin
data_buf <=
1'b0;
tr_state <= tr_idle;
tr_mem_addr <=
1'b0;
endelse
case
(tr_state)
tr_idle:
//初始化狀態
begin
req <=
1'b0;
tr_mem_addr <=
1'b0;
tr_state <= snd_data_req;
endsnd_data_req:
//送資料到匯流排上和傳送請求訊號
begin
data_buf <= tr_mem[tr_mem_addr]
; req <=
1'b1;
//傳送請求訊號,請求訊號為高,表示請求接收
tr_mem_addr <= tr_mem_addr +1;
tr_state <= chk_ack_active;
endchk_ack_active:
//檢測應答訊號為高,釋放請求訊號
begin
if(ack_reg2 ==
1'b1)
//便於時序收斂
begin
req <=
1'b0;
//釋放請求訊號
tr_state <= chk_comm_end;
endelse tr_state <= chk_ack_active;
endchk_comm_end:
//檢測握手通訊結束,如果應答訊號被釋放,一次握手結束
begin
if(ack_reg2 ==
1'b0)
tr_state <= snd_data_req;
else
tr_state <= chk_comm_end;
enddefault
:tr_state <= tr_idle;
endcase
endassign dout = data_buf;
endmodule
module woshou_rx
( input rst_n,
input r_clk,
input req,
input [7:
0] din,
output reg ack )
;reg req_reg1,req_reg2;
reg [2:
0] re_state;
reg [7:
0] re_mem_addr;
reg [7:
0] re_mem[
255:0]
;parameter re_idle=
3'b000, chk_req_active=3'b001, chk_req_release=
3'b010;
always@(posedge r_clk or negedge rst_n)
begin
if(!rst_n)
begin
req_reg1 <=
1'b0;
req_reg2 <=
1'b0;
endelse
begin
req_reg1 <= req;
req_reg2 <= req_reg1;
end
end//
always@(posedge r_clk or negedge rst_n)
begin
if(!rst_n)
begin
re_state <= re_idle;
ack <=
1'b0;
re_mem_addr <=
1'b0;
endelse
case
(re_state)
re_idle:
//初始化狀態
begin
re_mem_addr <=0;
re_state <= chk_req_active;
endchk_req_active:
//檢測傳送端的資料傳送請求訊號
begin
if(req_reg2 ==1)
//如果有請求訊號,接收資料
begin
re_state <= chk_req_release;
re_mem_addr <= re_mem_addr +1;
re_mem[re_mem_addr]
<= din;
//接收資料存放到mem
ack <=
1'b1;
//檢測到請求訊號,傳送接收端應答訊號
endelse re_state <= chk_req_active;
endchk_req_release:
//檢測請求訊號釋放,釋放應答訊號
begin
if(req_reg2 ==0)
begin
ack <=
1'b0;
//釋放應答訊號,一次握手通訊結束
re_state <= chk_req_active;
endelse re_state <= re_idle;
enddefault
: re_state <= re_idle;
endcase
endendmodule
pcie握手機制 PCIe匯流排的通訊機制
pcie 匯流排的通訊機制 在介紹事務層之前,首先簡單地了解一下 pcie 匯流排的通訊機制。假設某 個裝置要對另乙個裝置進行讀取資料的操作,首先這個裝置 稱之為 requester 需要向另乙個裝置傳送乙個 request 然後另乙個裝置 稱之為 completer 通過completion pa...
pcie握手機制 PCIe匯流排的熱插拔機制
pcie 匯流排的熱插拔機制 某些特殊的應用場合可能要求 pcie 裝置能夠以高可靠性持續不間斷運 行,為此,pcie 匯流排採用熱插拔 hotplug 和熱切換 hotswap 技術,來實現不關閉系統電源的情況下更換 pcie 卡裝置。注 本文將簡單地介紹一下 pcie 匯流排的熱插拔機制,關於熱...
TCP三次握手機制
seq是序列號,這是為了連線以後傳送資料用的,ack是對收到的資料報的確認,值是等待接收的資料報的序列號。在第一次訊息傳送中,a隨機選取乙個序列號作為自己的初始序號傳送給b 第二次訊息b使用ack對a的資料報進行確認,因為已經收到了序列號為x的資料報,準備接收序列號為x 1的包,所以ack x 1,...