<數字IC設計> 實戰專案之GPIO埠設計 3

IC跳跳魚發表於2020-10-08

GPIO之控制器設計

GPIO的控制器設計需要結合GPIO本身邏輯功能共同設計。
根據常識我們知道,晶片不止有一個GPIO口,所以在設計的時候有兩種路線:

  1. 晶片的每一個GPIO模組均為獨立模組(一次設計,N次例化)。
  2. 複用設計,設計一個GPIOs模組,模組內部包括多個GPIO埠。

一個普通的晶片一般擁有十餘個GPIO埠,較大的晶片可以用於二十個乃至更多的GPIO埠。那麼如何選擇合適的設計呢?

在這裡我的看法是根據模組本身的應用場景進行設計。一般來說,GPIO這種必要但是複雜度並不高的模組在設計中主要注重功能的完整性及程式碼的質量。設計結構最好是可以複用及移植。所以我認為單個模組只有一個GPIO埠的設計方式更好,但是在有些場景中,如果晶片在設計過程中本身可以使用的資源比較有限,那麼在設計GPIO埠模組的時候就需要仔細的斟酌來降低GPIO模組的資源消耗。

設計一個單GPIO埠的模組需要一個暫存器作為控制暫存器,設計NGPIO埠的模組就需要對控制暫存器的數量及種類進行劃分,從而用較少的暫存器控制更多的GPIO埠。比如一般來說應用中一個暫存器有32bit,若用暫存器組進行控制,那麼一組暫存器就可以控制最多32個埠。而單埠GPIO模組需要一個暫存器,若暫存器組的數量<GPIO埠數,則用NGPIO埠設計更加節省資源。

(某種程度上來說,這種針對場景進行設計優化正是我們作為基層晶片設計工程師存在的意義,如果不是這種需求,我想那些EDA大廠早已寫出一大堆指令碼取代我們這些基層員工了吧,哈哈。

確定了控制模式之後(這裡我們使用單GPIO模組設計),我們將暫存器命名為gpio_ctrl,暫存器為32-bits W/R。
根據GPIO埠設計 1我們可以發現,在實現功能過程中需要加鎖,鎖的存在是有意義的,因為主機有可能無意間因為誤發改變了我們配置暫存器的值,如果我們的埠配置立馬就針對這些改變進行了變化,那麼這種靈敏性會極大的降低我們模組的穩定性。鎖的設計我們使用if-else結構實現。

always (posedge clk or posedge reset)
begin
	if (reset)
		gpio_ctrl1 <= 6'b00_0000;
		gpio_cfg[2:0] <= 3'b000;
	else begin
			if (gpio_ctrl1[1:0] == 2'b01) begin
				if(gpio_ctrl1[3:2] == 2'b11) begin
					if(gpio_ctrl1[5:4] == 2'b10) begin
						gpio_cfg[2:0] <= gpio_ctrl[4:2];
						gpio_ctrl1 <= 6'b00_0000;
					end
					else begin
						gpio_ctrl1[5:4] <= gpio_ctrl[1:0];
					end
				end
				else begin
					gpio_ctrl1[3:2] <= gpio_ctrl[1:0];
				end
			end
			else	
				gpio_ctrl1[1:0] <= gpio_ctrl[1:0];
	end
end

通過以上結構,我們實現了鎖的功能。使用復位使用上升沿復位而非下降沿復位,也是為了提高設計的可靠性。

接下來就用剩下的位來實現其他功能的配置,利用狀態機實現對GPIO埠模式的配置:

localparam inputdata = 000,outputdata=001,test_mode = 010, alternate_function = 011; 
//if we want to add more alternate functions,  we can add more parameters to achieve our aim
always (posedge clk or posedge reset)
begin
	if (reset)
		****
	else begin
		case (gpio_cfg)
		*****
		endcase
	end
end

綜上所述,我們GPIO模組的設計就完成了,如需詳細程式碼記得私信我哦。

相關文章