【地址区间划分】
地址区间划分
- 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)