地址區間劃分
- 1 decode_addr
- 1.1 地址區間
- 1.2 變式
本篇博客主要介紹對地址區間劃分的一個比較巧妙參數化的做法。
1 decode_addr
遇到一個master轉多個slave時,不可避免需要進行對addr總線進行分配地址區間來進行選中;
在這里給出一個可復用且設計思想比較巧妙的做法;
parameter SLAVE0_BASE = 32'h00000000;
parameter SLAVE0_MASK = 32'hFFE00000;
parameter SLAVE1_BASE = 32'h00200000;
parameter SLAVE1_MASK = 32'hFFE00000;function automatic [1:0] decode_address;input [ADDR_WIDTH-1:0] addr;beginif ((addr & SLAVE0_MASK) == SLAVE0_BASE)decode_address = 2'b00; // 選擇從設備0else if ((addr & SLAVE1_MASK) == SLAVE1_BASE)decode_address = 2'b01; // 選擇從設備1else decode_address = 2'b10; // 默認或錯誤end
endfunction
1.1 地址區間
根據代碼中的參數和地址解碼邏輯,地址范圍計算如下:
從設備0 (SLAVE0) 地址范圍:
基地址:32’h00000000
掩碼:32’hFFE00000 (高11位為1,低21位為0)
有效地址范圍:32’h00000000 ~ 32’h001FFFFF
計算方式:基地址 + (2^21 - 1)
從設備1 (SLAVE1) 地址范圍:
基地址:32’h00200000
掩碼:32’hFFE00000 (同上)
有效地址范圍:32’h00200000 ~ 32’h003FFFFF
計算方式:基地址 + (2^21 - 1)
地址匹配規則:
地址高11位必須嚴格匹配基地址的高11位
低21位可以是任意值(0~0x1FFFFF)
每個從設備的地址空間大小為2MB(2^21字節)
1.2 變式
在這里我想選擇地址區間是1MB的時候,只需修改參數即可,代碼如下:
parameter SLAVE0_BASE = 32'h00000000;
parameter SLAVE0_MASK = 32'hFFF00000;
parameter SLAVE1_BASE = 32'h00100000;
parameter SLAVE1_MASK = 32'hFFF00000;function automatic [1:0] decode_address;input [ADDR_WIDTH-1:0] addr;beginif ((addr & SLAVE0_MASK) == SLAVE0_BASE)decode_address = 2'b00; // 選擇從設備0else if ((addr & SLAVE1_MASK) == SLAVE1_BASE)decode_address = 2'b01; // 選擇從設備1else decode_address = 2'b10; // 默認或錯誤end
endfunction
從設備0 (SLAVE0) 地址范圍
基地址:32’h00000000
掩碼:32’hFFF00000 (高12位為1,低20位為0)
有效地址范圍:32’h00000000 ~ 32’h000FFFFF
地址空間大小:1MB (2^20字節)
匹配規則:地址高12位必須等于000(二進制)
從設備1 (SLAVE1) 地址范圍
基地址:32’h00100000
掩碼:32’hFFF00000 (同上)
有效地址范圍:32’h00100000 ~ 32’h001FFFFF
地址空間大小:1MB (2^20字節)
匹配規則:地址高12位必須等于001(二進制)
關鍵變化說明(相比原配置)
掩碼改為12位:FFE00000 → FFF00000(地址匹配精度從11位提高到12位)
空間大小減半:每個從設備地址空間從2MB變為1MB
設備1基地址調整:00200000 → 00100000(間隔從2MB變為1MB)
地址解碼示例
0x00012345 → 匹配設備0(高12位=0x000)
0x001ABCDE → 匹配設備1(高12位=0x001)
0x00200000 → 不匹配任何設備(返回2’b10)