加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 一、MCU和CPLD直接交互
    • 二、mcu通過(guò)ahb轉(zhuǎn)apb后的數(shù)據(jù)交互
    • 三、DMA在CPLD中的使用
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

AG32:MCU和CPLD交互實(shí)操指南

09/26 14:49
1903
閱讀需 20 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

本文檔介紹了AG32開(kāi)發(fā)中,MCU與CPLD交互的具體方式以及例子。

如需了解AG32更多資料可發(fā)郵件:sales@agm-micro.com,或直接掃碼加我本人微信。

一、MCU和CPLD直接交互

cpld工程創(chuàng)建及編譯的操作流程,參考文檔《AG32下fpga和cpld的使用入門(mén)》

在工程中,用戶邏輯部分編寫(xiě)是從analog_ip.v的接口下開(kāi)始的。

mcu和cpld之間的交互,可以分為:

1. mcu傳遞信號(hào)給cpld;(如mcu的gpio傳遞高低信號(hào)到cpld)

2. cpld傳遞信號(hào)給mcu;(如:對(duì)mcu產(chǎn)生中斷信號(hào))

3. mcu讀寫(xiě)數(shù)據(jù)到cpld;

4. 不建議,cpld做為主設(shè)備對(duì)mcu寫(xiě)。

也就是說(shuō),在mcu和cpld交互中,cpld更像一個(gè)外設(shè)。

其中,前兩種較為簡(jiǎn)單。后兩種要使用AHB總線來(lái)操作。

下邊針對(duì)四種情況分別說(shuō)明:

1. mcu傳遞信號(hào)給cpld;

這種使用較簡(jiǎn)單。步驟如下:

在ve中定義信號(hào):

GPIO4_1
iocvt_chn:OUTPUT

表示,用mcu的gpio(gpio4_1)來(lái)輸入信號(hào)到cpld。

然后,prepare LOGIC工程后,可以看到analog_ip.v接口中的信號(hào):

input?????????????iocvt_chn_out_data,

input?????????????iocvt_chn_out_en,

這里的iocvt_chn_out_data,就是對(duì)接到mcu的gpio4_1的信號(hào)。

當(dāng)控制mcu的gpio4_1高低切換時(shí),cpld中的iocvt_chn_out_data,會(huì)對(duì)應(yīng)來(lái)變化。

具體樣例,可以參考網(wǎng)盤(pán)“l(fā)ogic樣例3.mcu信號(hào)到cpld到pin”的樣例,該樣例中,展示了mcu控制cpld繼續(xù)控制led的過(guò)程。

除了gpio信號(hào)輸出到cpld,其他比如pwm輸出信號(hào)等,都可以輸入到cpld。

2. cpld傳遞信號(hào)給mcu

這種方式和1相近,只不過(guò)是反向。

可以在mcu中定義gpio4_2為輸入并使能中斷,則cpld中設(shè)置信號(hào)高低時(shí),將觸發(fā)?mcu的中斷。

在VE中定義信號(hào):

GPIO4_2
iocvt_chn:INPUT

表示,用mcu的gpio(gpio4_2)信號(hào)來(lái)源于cpld的iocvt_chn。

然后,prepare LOGIC工程后,可以看到analog_ip.v接口中的信號(hào):

output?????????????iocvt_chn_in_data,

這里的iocvt_chn_in_data,就是對(duì)接到mcu的gpio4_2的信號(hào)。

當(dāng)cpld中控制iocvt_chn_in_data信號(hào)高低時(shí),mcu中的gpio4_2對(duì)應(yīng)變化。

這里不再舉例。

3. mcu讀寫(xiě)數(shù)據(jù)到cpld;

在地址設(shè)計(jì)中,cpld的地址區(qū)間是:0x60000000 ~
0x7FFFFFFF

當(dāng)mcu對(duì)這個(gè)區(qū)間內(nèi)的地址訪問(wèn)時(shí),相當(dāng)于訪問(wèn)了cpld的“寄存器”。

mcu是全局尋址,對(duì)這個(gè)空間的訪問(wèn)和對(duì)ram(0x20000000起)空間的訪問(wèn)是一樣的方式,在C代碼中,可以這樣寫(xiě):

讀cpld:int cpRdReg = *((int *)0x60000000);

寫(xiě)cpld:*((int *)0x60000004) = cpWtReg;

Mcu端讀寫(xiě)cpld較為簡(jiǎn)單,直接通過(guò)上述語(yǔ)句就可以了。

當(dāng)mcu讀寫(xiě)動(dòng)作發(fā)生時(shí),cpld端是如何反應(yīng)的?

當(dāng)上述mcu讀寫(xiě)動(dòng)作發(fā)生時(shí),AHB總線會(huì)把動(dòng)作拆解為讀寫(xiě)信號(hào),傳遞到analog_ip.v的接口,用戶cpld程序需要響應(yīng)該信號(hào)。

以下,以寫(xiě)動(dòng)作 *((int *)0x60000004) = cpWtReg 為例,描述cpld端會(huì)發(fā)生的事情。

回顧下analog_ip.v中的接口部分:

其中slave_ahb_開(kāi)頭的一組信號(hào),是cpld作為主端時(shí)用的,暫時(shí)不用理會(huì)。

Mem_ahb_開(kāi)頭的一組信號(hào),是cpld作為從端使用的。

當(dāng)mcu有讀寫(xiě)操作時(shí),mem_ahb_這組信號(hào)將發(fā)生變化。

這部分是遵循標(biāo)準(zhǔn)的AHB總線協(xié)議的。如果對(duì)AHB總線印象不深,請(qǐng)自行百度

可參考的講解:https://blog.csdn.net/weixin_46022434/article/details/104987905

幾個(gè)信號(hào)的概述(更詳細(xì)的講解請(qǐng)自行百度):

Ahb_htrans: 當(dāng)前傳輸類型(00: IDLE、01: BUSY、10: NONSEQ、11: SEQ)

Ahb_ready:mcu讀時(shí)要mcu要準(zhǔn)備好cpld才會(huì)寫(xiě)

Ahb_hwrite: 要讀還是要寫(xiě)(1為寫(xiě),0為讀)

Ahb_haddr[32]: 要操作的地址

Ahb_hsize:transfer的大小,以字節(jié)為單位

Ahb_hburst:批量傳輸

Ahb_hwdata[32]:寫(xiě)的數(shù)據(jù),32位

Ahb_hreadyout:輸出信號(hào),mcu寫(xiě)時(shí)cpld是否準(zhǔn)備好

Ahb_hresp:輸出信號(hào),響應(yīng)信號(hào)(OK、retry、error、split)

Ahb_hrdata[32]:讀的數(shù)據(jù),32位

根據(jù)AHB時(shí)序,在一次傳輸中,cpld(slave端)會(huì)先拿到addr地址,讀或?qū)懙臉?biāo)記,然后交互ready信號(hào)后,開(kāi)始數(shù)據(jù)傳輸。

大致如下圖(無(wú)等待類型的圖):

比如,mcu要讀0x60000004的寄存器:

mcu端直接C語(yǔ)言這樣調(diào)用:int cpRdReg = *((int
*)0x60000004);

cpld端,可以根據(jù)以上信號(hào)做如下處理:

----------------------------------------------

//mcu的讀操作響應(yīng)

//mcu端用C語(yǔ)言:int value = *((int *)0x60000004);

reg [31:0] hrdata_reg; ?????? //定義32位的hrdata_reg

always @(posedge sys_clock) begin??????? //clk上升沿觸發(fā)

if (mem_ahb_htrans ==
2'b10 &&? ???????? //NONSEQ
狀態(tài),第一次傳輸

? mem_ahb_hready && ??????????????? ????????? //master已ready,可以給數(shù)據(jù)線寫(xiě)入了

? !mem_ahb_hwrite &&??????? ???????? //(0 讀,1 寫(xiě))

? mem_ahb_haddr[23:0] == 'h04) ??????? //讀地址為0x60000004(cpld用相對(duì)偏移)

begin

hrdata_reg <=
hwdata_reg;????????????? //
把另一準(zhǔn)備好的數(shù)據(jù)給到hrdata_reg

end

end

assign mem_ahb_hrdata = hrdata_reg; //綁定hrdata_reg到讀的數(shù)據(jù)線上

-----------------------------------------------

以上代碼,加入到analog_ip.v的module下,就可以完成cpld對(duì)mcu讀動(dòng)作的響應(yīng)。

比如,mcu要寫(xiě)0x60000000的寄存器:

mcu端直接C語(yǔ)言這樣調(diào)用:*((int *)0x60000000)
= value;

cpld端,可以根據(jù)以上信號(hào)做如下處理:

----------------------------------------------

//mcu的寫(xiě)操作響應(yīng)

//mcu端用C語(yǔ)言:*((int *)0x60000000) = value;

reg [31:0] hwdata_reg; ?????? //定義32位的hwdata_reg

always @(posedge sys_clock) begin??????? //clk上升沿觸發(fā)

if (mem_ahb_htrans ==
2'b00 &&? ?????? //IDLE
狀態(tài)

? mem_ahb_hreadyout && ????????? ???????? //cpld已ready狀態(tài),ahb上數(shù)據(jù)可以寫(xiě)過(guò)來(lái)

? mem_ahb_hwrite &&??????? ????????? //寫(xiě)(0 讀,1 寫(xiě))

? mem_ahb_haddr[23:0] == 'h00) ??????? //寫(xiě)地址為0x60000000(cpld用相對(duì)偏移)

begin

hwdata_reg <=
mem_ahb_hwdata;???????? //
把收到的數(shù)據(jù)給到hwdata_reg

end

end

//這個(gè)過(guò)程,是把mcu寫(xiě)進(jìn)來(lái)的數(shù)據(jù)收到hwdata_reg

-----------------------------------------------

這部分的實(shí)例代碼,請(qǐng)參考網(wǎng)盤(pán)上cpld樣例工程《5.mcu讀寫(xiě)cpld寄存器》。

注意:這里展示的,僅僅是基于AHB總線上的數(shù)據(jù)交互。

在實(shí)際應(yīng)用中,比如要實(shí)現(xiàn)一個(gè)串口之類的,往往是慢速設(shè)備,這些是要掛載到apb ? 上的。慢速設(shè)備要經(jīng)過(guò)ahb到apb的bridge,才能最終使用。請(qǐng)繼續(xù)往下看。

二、mcu通過(guò)ahb轉(zhuǎn)apb后的數(shù)據(jù)交互

上節(jié)講述了mcu和cpld之間交互數(shù)據(jù)的實(shí)現(xiàn)方式。

但數(shù)據(jù)是在ahb層面的響應(yīng),慢速設(shè)備不能直接使用。

慢速設(shè)備需要ahb轉(zhuǎn)為apb后,使用apb的信號(hào)來(lái)交互。這種情況,轉(zhuǎn)變?yōu)閙cu和apb? 之間的交互。

mcu和apb之間的交互,相比mcu和aph之間的交互,多了一層ahb到apb的轉(zhuǎn)換。這個(gè)轉(zhuǎn)換是借助于ahb2apb.v模塊來(lái)實(shí)現(xiàn)的(在example/analog下找該.v文件)。

該模塊:輸入是ahb的一組信號(hào),輸出是apb的一組信號(hào)。使用如下圖:

如果實(shí)現(xiàn)mcu和apb的交互,則需要操作的是轉(zhuǎn)換后的這組apb信號(hào)。

關(guān)于apb總線的使用,更多信息請(qǐng)自行百度。

這里只是簡(jiǎn)述下apb信號(hào)列表(與ahb略有不同):

apb_psel:片選

apb_penable:表示傳輸進(jìn)入第二周期(準(zhǔn)備好了讀/寫(xiě))

apb_pwrite:傳輸方向(1-寫(xiě);0-讀)

apb_paddr[32]:地址總線,要操作的地址

apb_pwdata[32]:寫(xiě)的數(shù)據(jù),32位

apb_prdata[32]:讀的數(shù)據(jù),32位

以下展示在apb下如何實(shí)現(xiàn)跟mcu的交互,仍以ahb的兩個(gè)寄存器為例。

1. 首先需要增加ahb轉(zhuǎn)apb的信號(hào)關(guān)聯(lián);

如上圖。

Ahb2apb模塊會(huì)把a(bǔ)hb信號(hào)轉(zhuǎn)換為apb信號(hào)。接下來(lái)操作apb信號(hào)即可。

2. 在轉(zhuǎn)換后的apb信號(hào)中,實(shí)現(xiàn)寫(xiě)和讀的操作。

mcu讀操作時(shí):

比如,mcu要讀0x60000004的寄存器:

mcu端直接C語(yǔ)言這樣調(diào)用:int cpRdReg = *((int
*)0x60000004);

cpld端,可以根據(jù)以上信號(hào)做如下處理:

----------------------------------------------

//mcu的讀操作響應(yīng)

//mcu端用C語(yǔ)言:int value = *((int *)0x60000004);

reg [31:0] ardata_reg; ?????? //定義32位的hrdata_reg

always @(posedge apb_clock) begin????? //clk上升沿觸發(fā)

if (!apb_pwrite
&&??????? ???????????????????? //
(0 讀,1 寫(xiě))

apb_penable
&&???????????????????????????????? //
是否準(zhǔn)備好

apb_paddr[11:0]
== ‘h04)??? //
讀地址為0x60000004(cpld內(nèi)部用相對(duì)偏移)

begin

ardata_reg <=
awdata_reg;????????????? //
把另一準(zhǔn)備好的數(shù)據(jù)給到hrdata_reg

end

end

assign apb_prdata = ardata_reg; //綁定hrdata_reg到讀的數(shù)據(jù)線上

-----------------------------------------------

mcu寫(xiě)操作時(shí):

比如,mcu要寫(xiě)0x60000000的寄存器:

mcu端直接C語(yǔ)言這樣調(diào)用:*((int *)0x60000000)
= value;

cpld端,可以根據(jù)以上信號(hào)做如下處理:

----------------------------------------------

//mcu的寫(xiě)操作響應(yīng)

//mcu端用C語(yǔ)言:*((int *)0x60000000) = value;

reg [31:0] awdata_reg; ?????? //定義32位的hwdata_reg

always @(posedge apb_clock) begin????? //clk上升沿觸發(fā)

if (apb_pwrite
&&??????? ????????????????????? //
寫(xiě) (0 讀,1 寫(xiě))

apb_penable
&&???????????????????????????????? //
是否準(zhǔn)備好

apb_paddr[11:0]
== ‘h00)? //
寫(xiě)地址為0x60000000(cpld內(nèi)部用相對(duì)偏移)

begin

awdata_reg <=
apb_pwdata;?????????? //
把收到的數(shù)據(jù)給到hwdata_reg

end

end

//這個(gè)過(guò)程,是把mcu寫(xiě)進(jìn)來(lái)的數(shù)據(jù)收到hwdata_reg

-----------------------------------------------

這個(gè)功能實(shí)現(xiàn)后,其實(shí)是個(gè)簡(jiǎn)單的“空外設(shè)”??梢杂盟鰹閷?shí)現(xiàn)復(fù)雜功能外設(shè)的基礎(chǔ)。

這部分的實(shí)例代碼,請(qǐng)參考網(wǎng)盤(pán)上cpld樣例工程《5.mcu讀寫(xiě)cpld寄存器》。

樣例展示到這里,mcu和cpld的交互上:交互信號(hào)、跟ahb交互數(shù)據(jù)、跟apb交互數(shù)據(jù),基本的交互通路已經(jīng)建立。

接下來(lái),用戶根據(jù)自己的需求,在cpld中交互到數(shù)據(jù)后,編寫(xiě)自己需要的功能即可。

三、DMA在CPLD中的使用

cpld中實(shí)現(xiàn)DMA的邏輯:

1. MCU為master,cpld為slave,mcu對(duì)cpld的交互方式為存取寄存器的方式;

2. mcu中配置好DMA(讀取cpld中準(zhǔn)備好的數(shù)據(jù));

3. cpld中準(zhǔn)備好數(shù)據(jù)后,觸發(fā)dma信號(hào),dma自動(dòng)搬運(yùn)到mcu指定的ram;

4. 搬運(yùn)一次后,dma給cpld一個(gè)clear信號(hào),完成一次dma搬運(yùn);

5. 等到cpld中再次準(zhǔn)備好數(shù)據(jù),將再次觸發(fā)dma信號(hào),重復(fù)3和4;

對(duì)于cpld來(lái)說(shuō),mcu來(lái)讀取數(shù)據(jù)和dma來(lái)讀取數(shù)據(jù),是一致的。

dma來(lái)讀取時(shí),只是每次讀完后會(huì)多給cpld一個(gè)clear信號(hào)。

更多細(xì)節(jié),請(qǐng)參考網(wǎng)盤(pán)上《7.cpld中配合實(shí)現(xiàn)mcu的dma讀取》部分的樣例。

在這個(gè)樣例中,展示了兩部分代碼:

1. mcu中,配置dma讀?。粸榱藴y(cè)試,mcu會(huì)在另一地址給cpld寫(xiě)數(shù)據(jù);

2. cpld中,會(huì)對(duì)mcu寫(xiě)進(jìn)來(lái)的數(shù)據(jù)緩存,緩存后觸發(fā)dma的信號(hào),讓dma來(lái)讀取數(shù)據(jù)。而dma從cpld里讀取數(shù)據(jù)后會(huì)給cpld一個(gè)clear信號(hào),標(biāo)志一次dma交互完成。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜