對MCDT設計模塊的理解

MCDT是MCDF的縮減版贱案,MCDT比MCDF(multi-channel data formatter)少了寄存器配置模塊(Registers)和整型打包數(shù)據(jù)模塊(Formater)永淌。


1. Slave_fifo

此模塊是

Slave部分與FIFO部分結(jié)合的模塊,一共分別有3個Slave和3個FIFO贞言,對應3個發(fā)送激勵的chnl模塊砰粹。

module slave_fifo (

input? ? ? ? ? ? ? ? ? ? ? clk_i,? ? ? ? ? ? ? ? ?// Clock input

input? ? ? ? ? ? ? ? ? ? ? rstn_i,? ? ? ? ? ? ? ?// Reset signal

input [31:0]? ? ? ? ? ? ? ? chx_data_i,? ? ? ? ? ?// 來自外部的數(shù)據(jù)輸入孵稽,這里即是來自Chnl發(fā)送的激勵數(shù)據(jù)輸入政模。

input? ? ? ? ? ? ? ? ? ? ? a2sx_ack_i,? ? ? ? ? ? // Read ack? ? ? ? ? ? ? ? ? ---->來自Aribiter的反饋輸入呐粘,Aribiter要響應并從你這里讀FIFO中的數(shù)據(jù)满俗,ack意思是我(Aribiter)是否現(xiàn)在可以行動起來從你FIFO拿數(shù)據(jù)了。

input? ? ? ? ? ? ? ? ? ? ? chx_valid_i,? ? ? ? ? ? // Data is valid From outside ---->來自外部的控制信號作岖,告訴Slave唆垃,我(Chnl)此次發(fā)送的數(shù)據(jù)data做不做數(shù)。

output reg [31:0]? ? ? ? ? slvx_data_o,? ? ? ? ? ? // Data Output? ? ? ? ? ? ? ? ---->向Arbiter輸出的數(shù)據(jù)痘儡,x表示從哪一個slave來都有可能辕万。

output [5:0]? ? ? ? ? ? ? ? slvx_margin_o,? ? ? ? ? // Data margin? ? ? ? ? ? ? ---->告訴外部/寄存器模塊,我現(xiàn)在還剩余多少空位沉删,你還可以繼續(xù)發(fā)送數(shù)據(jù)渐尿。

output reg? ? ? ? ? ? ? ? ? chx_ready_o,? ? ? ? ? ? // Ready to accept data? ? ? ---->告訴外部(Chnl),我準備好了矾瑰,有空位砖茸,你可以發(fā)送數(shù)據(jù)進來。

output reg? ? ? ? ? ? ? ? ? slvx_val_o,? ? ? ? ? ? // Output data is valid? ? ? ---->告訴下游Arbiter殴穴,我發(fā)出的數(shù)據(jù)是否有效凉夯,可以類比chx_valid_i

output reg? ? ? ? ? ? ? ? ? slvx_req_o? ? ? ? ? ? ? // Request to send data? ? ? ---->告訴下游Arbiter货葬,我需要發(fā)送數(shù)據(jù)出去了。

);? ?

//------------------------------Internal variables-------------------//

reg [5:0] wr_pointer_r; ? ? ? // 內(nèi)部變量劲够,表示FIFO的寫操作指針宝惰。

reg [5:0] rd_pointer_r; ? ? ? ?//內(nèi)部變量,表示FIFO的讀操作指針再沧。

reg [31:0] mem [0:31]; ? ? ?// 一個[31:0]寬,32bit深的FIFO尊残。

//-----------------------------Variable assignments------------------//

wire full_s, empty_s, rd_en_s ; ? ? ? // 由我上一篇文章寫的炒瘸,這是代表信號線,可以傳遞指示狀態(tài)寝衫。

wire [5:0] data_cnt_s; ? ? ? ?// 一捆線顷扩,由6根信號線組成,可以指示FIFO當前的余量狀態(tài)慰毅。

assign full_s = ({~wr_pointer_r[5], wr_pointer_r[4:0]}==rd_pointer_r); ? ? // ?滿狀態(tài)的標志隘截,邏輯是寫指針的最高位取反,寫指針最高位達到1了肯定就滿了汹胃,因為我們的FIFO是32位深的婶芭,2^5就能表示32了(`b100_000),在達到最大值32之前着饥,寫指針的最高位都是0犀农。因此可以通過最高位取反與讀指針做比較來判斷當前是否是滿狀態(tài)。

assign empty_s = (wr_pointer_r == rd_pointer_r); ?// 空狀態(tài)宰掉,其實空狀態(tài)和滿狀態(tài)呵哨,讀寫指針都相等,但在上一行已經(jīng)通過最高位可以判斷此時是空還是滿轨奄。

assign data_cnt_s = (6'd32 - (wr_pointer_r - rd_pointer_r)); ? // 簡單的數(shù)學計算孟害,剩余空位 = 寫入數(shù) - 讀出數(shù)。

assign slvx_margin_o = data_cnt_s; ? // 將剩余空位信號挪拟,驅(qū)動到margin信號上挨务。

assign rd_en_s = a2sx_ack_i; ? // 將Arbiter反饋的可讀信號線,驅(qū)動到read_enable信號線上舞丛,這根信號線有用耘子。

隊列的操作(FIFO)

always @ (*) //ready signal

begin

????if (!full_s) chx_ready_o = 1'b1; ? ? ? ? ? ??// 如果滿信號為0,說明還沒滿球切,把ready信號線拉高谷誓,說明準備可以接收數(shù)據(jù)了。? ? ?

????else chx_ready_o = 1'b0;? ? ? ? ? ? ? ?// 如果滿信號為1吨凑,拉低ready捍歪。

end

always @ (*) //reset signal

begin

? ????if (!rstn_i) slvx_req_o = 1'b0; ? ? ?// 復位信號户辱,低有效,意思rstn_i拉低糙臼,說明我們要進行重制庐镐,把req請求信號拉低,代表我們不往下游發(fā)送數(shù)據(jù)变逃。

????? else if (!empty_s) slvx_req_o = 1'b1;? ? ? ? ? // ?不復位必逆,且empty信號為0,代表我現(xiàn)在FIFO不為空揽乱,拉高req名眉,表明我需要把我FIFO的數(shù)據(jù)排空到下游Arbiter。

? ????else slvx_req_o = 1'b0; ? // 不復位凰棉,但FIFO為空损拢,發(fā)也沒得發(fā)了,拉低req撒犀。

end


// 寫指針的運作原理

always @ (posedge clk_i or negedge rstn_i) ? ? ? ?// 時鐘上升沿或重置信號下降沿觸發(fā)

begin :?

? if (!rstn_i) begin ? ? ?// ?復位福压,寫指針清零,同時也代表著我FIFO里被清零了或舞。

? ? wr_pointer_r <= 6'b0000;

? end else

? if (chx_valid_i && chx_ready_o) begin ? ? ? ? // ?valid信號拉高荆姆,且ready信號拉高,不僅我Chnl準備好了映凳,我的Slave和FIFO也準備好了胞枕,開始寫入數(shù)據(jù)到FIFO。(具體寫操作在下面魏宽,此處僅對寫指針做操作)

? ? wr_pointer_r <= wr_pointer_r + 6'b0001; ? ? // 每寫一個數(shù)據(jù)腐泻,指針+1

? end

end

//????讀指針加法

always @ (posedge clk_i or negedge rstn_i)

begin : READ_POINTER

? if (!rstn_i) begin

? ? rd_pointer_r <= 6'b0000;

? end else

? if (rd_en_s && (!empty_s)) begin ? ?// ?當下游Arbiter可以從FIFO讀數(shù)據(jù)了,并且我的FIFO不為空的時候队询,開始讀取數(shù)據(jù)派桩。(具體讀操作在下面,此處只對讀指針做+1操作)

? ? rd_pointer_r <= rd_pointer_r + 6'b0001;

? end

end


// 數(shù)據(jù)輸出有效信號的操作(slave-FIFO給Arbiter的valid信號)

always @ (posedge clk_i or negedge rstn_i)

begin

? if (!rstn_i) slvx_val_o <= 1'b0;

? ????????else if (rd_en_s && (!empty_s)) ? ? ?// ?下游的 Arbiter可以讀數(shù)據(jù)蚌斩,并且不為空铆惑,此處其實與上一塊代碼重合,可以優(yōu)化送膳。

? ????????? slvx_val_o <= 1'b1; ? ? ?// ?拉起valid

? else slvx_val_o <= 1'b0; ? ?// ?拉低valid

end

// ?FIFO讀數(shù)據(jù)

always? @ (posedge clk_i )

begin : READ_DATA

? if (rstn_i && rd_en_s && (!empty_s)) begin ??

? ????? slvx_data_o <= mem[rd_pointer_r[4:0]]; ? // ?將FIFO中讀指針對應位置的數(shù)據(jù)拿出员魏,賦給slvx_data_out

? end

end

// FIFO寫數(shù)據(jù)

always @ (posedge clk_i)

begin : MEM_WRITE

? if (rstn_i && chx_valid_i && chx_ready_o) begin

? ? mem[wr_pointer_r[4:0]] <= chx_data_i; ? // ?將此時Chnl傳遞來的數(shù)據(jù),寫入到FIFO中寫指針對應的位置叠聋。

? end

end


2. Arbiter

module arbiter(

input ? ? ? ? ? ? ? ? ? ?clk_i,

input ? ? ? ? ? ? ? ? ? ?rstn_i,

//connect with slave port

input ?[31:0] ? ? ? ? ? ?slv0_data_i,

input ?[31:0] ? ? ? ? ? ?slv1_data_i,

input ?[31:0] ? ? ? ? ? ?slv2_data_i,

input ? ? ? ? ? ? ? ? ? ?slv0_req_i,

input ? ? ? ? ? ? ? ? ? ?slv1_req_i,

input ? ? ? ? ? ? ? ? ? ?slv2_req_i,

input ? ? ? ? ? ? ? ? ? ?slv0_val_i,

input ? ? ? ? ? ? ? ? ? ?slv1_val_i,

input ? ? ? ? ? ? ? ? ? ?slv2_val_i,

output ? ? ? ? ? ? ? ? ? a2s0_ack_o,? ? // 輸出到上游FIFO端

output ? ? ? ? ? ? ? ? ? a2s1_ack_o,? ??

output ? ? ? ? ? ? ? ? ? a2s2_ack_o,

//Output of MCDT

output ? ? ? ? ? ? ? ? ? data_val_o,? ?// 輸出到下游外部

output [1:0] ? ? ? ? ? ? arb_id_o,

output [31:0] ? ? ? ? ? ?arb_data_o ? ? ?

);


reg ? ? ? ? ? ? ? ? ? data_val_r;

reg [1:0] ? ? ? ? ? ? arb_id_r;

reg [31:0] ? ? ? ? ? ?arb_data_r;

reg [2:0] ? ? ? ? ? ? c_state;

reg [2:0] ? ? ? ? ? ? n_state;

//--------------------------------use FSM to implete simple Round Robin Arbiter? ? ? ?輪詢狀態(tài)機? ? ? ? ? ? ? ? ? ? ? ?

parameter ? IDLE = 3'b000,

? ? ? ? ? ? GRANT0 = 3'b001,

? ? ? ? ? ? GRANT1 = 3'b010,

? ? ? ? ? ? GRANT2 = 3'b100;


always @ (posedge clk_i or negedge rstn_i)

begin

? if (!rstn_i) c_state <= IDLE;? // 初始狀態(tài)為IDLE

? else c_state <= n_state;?

end

always @ (*)

begin

? if (!rstn_i) n_state = IDLE;? //default priority slv0 > slv1 > slv2

? else

? ? case (c_state)

? ? ? IDLE : ?if (slv0_req_i) n_state = GRANT0;

? ? ? ? ? ? ? else if (slv1_req_i) n_state = GRANT1;

? ? ? ? ? ? ? else if (slv2_req_i) n_state = GRANT2;

? ? ? ? ? ? ? else n_state = IDLE;

? ? ?GRANT0 : if (slv1_req_i) n_state = GRANT1;

? ? ? ? ? ? ? else if (slv2_req_i) n_state = GRANT2;

? ? ? ? ? ? ? else if (slv0_req_i) n_state = GRANT0;

? ? ? ? ? ? ? else n_state = IDLE;

? ? ?GRANT1 : if (slv2_req_i) n_state = GRANT2;

? ? ? ? ? ? ? else if (slv0_req_i) n_state = GRANT0;

? ? ? ? ? ? ? else if (slv1_req_i) n_state = GRANT1;

? ? ? ? ? ? ? else n_state = IDLE;

? ? GRANT2 : if (slv0_req_i) n_state = GRANT0;

? ? ? ? ? ? ?else if (slv1_req_i) n_state = GRANT1;

? ? ? ? ? ? ?else if (slv2_req_i) n_state = GRANT2;

? ? ? ? ? ? ?else n_state = IDLE;

? ? default : n_state = IDLE;

? ? endcase

end

輪詢機制描述了狀態(tài)轉(zhuǎn)換撕阎,使得狀態(tài)機無論進入到哪一種狀態(tài),都可以進入到下一個狀態(tài)碌补,不至于鎖死虏束。例如:當前為IDLE狀態(tài)時棉饶,3個req信號都同時拉起了,一定是先進入GRANT0狀態(tài)镇匀,進入GRANT0之后照藻,即使req信號是同時拉起的狀態(tài),不會再進入GRANT0狀態(tài)了汗侵,而是會進入下一個GRANT1狀態(tài)幸缕。依次類推。


assign {a2s2_ack_o,a2s1_ack_o,a2s0_ack_o} = ?c_state;? // 狀態(tài)機映射到信號線

always @ (*)

begin

if (!rstn_i) begin

? ? data_val_r = 1'b0;

? ? arb_id_r = 2'b11;

? ? arb_data_r = 32'hffff_ffff;

? end

? else

? case ({slv2_val_i,slv1_val_i,slv0_val_i}) ? ?

? 3'b001 : begin

? ? ? ? data_val_r = slv0_val_i;

? ? ? ? ? ? arb_id_r = 2'b00;

? ? ? ? ? ? arb_data_r = slv0_data_i;

? ? ? ? end

? 3'b010 : begin

? ? ? ? ? ? data_val_r = slv1_val_i;

? ? ? ? ? ? arb_id_r = 2'b01;

? ? ? ? ? ? arb_data_r = slv1_data_i;

? ? ? ? ? ? end

? 3'b100 : begin

? ? ? ? ? ? data_val_r = slv2_val_i;

? ? ? ? ? ? arb_id_r = 2'b10;

? ? ? ? ? ? arb_data_r = slv2_data_i;

? ? ? ? ? ? end


? default : begin

? ? ? ? data_val_r = 1'b0;

? ? ? ? arb_id_r = 2'b11;

? ? ? ? arb_data_r = 32'hffff_ffff;

? ? ? ? end

? endcase


end

assign data_val_o = data_val_r;

assign arb_data_o = arb_data_r;

assign arb_id_o = arb_id_r;

endmodule

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晰韵,一起剝皮案震驚了整個濱河市冀值,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宫屠,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滑蚯,死亡現(xiàn)場離奇詭異浪蹂,居然都是意外死亡,警方通過查閱死者的電腦和手機告材,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門坤次,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斥赋,你說我怎么就攤上這事缰猴。” “怎么了疤剑?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵滑绒,是天一觀的道長。 經(jīng)常有香客問我隘膘,道長疑故,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任弯菊,我火速辦了婚禮纵势,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘管钳。我一直安慰自己钦铁,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布才漆。 她就那樣靜靜地躺著牛曹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪醇滥。 梳的紋絲不亂的頭發(fā)上躏仇,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天恋脚,我揣著相機與錄音,去河邊找鬼焰手。 笑死糟描,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的书妻。 我是一名探鬼主播船响,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躲履!你這毒婦竟也來了见间?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤工猜,失蹤者是張志新(化名)和其女友劉穎米诉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篷帅,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡史侣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了魏身。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惊橱。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖箭昵,靈堂內(nèi)的尸體忽然破棺而出税朴,到底是詐尸還是另有隱情,我是刑警寧澤家制,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布正林,位于F島的核電站,受9級特大地震影響颤殴,放射性物質(zhì)發(fā)生泄漏卓囚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一诅病、第九天 我趴在偏房一處隱蔽的房頂上張望哪亿。 院中可真熱鬧,春花似錦贤笆、人聲如沸蝇棉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篡殷。三九已至,卻和暖如春埋涧,著一層夾襖步出監(jiān)牢的瞬間板辽,已是汗流浹背奇瘦。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留劲弦,地道東北人耳标。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像邑跪,于是被迫代替她去往敵國和親次坡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容