請閱讀【ARM AMBA 總線 文章專欄導讀】
文章目錄
- APB 寄存器訪問
- APB 讀寄存器 RTL 代碼實現
- APB 寫寄存器 RTL 代碼實現
APB 寄存器訪問
APB 讀寄存器 RTL 代碼實現
APB 總線讀寄存器操作代碼實現:
wire [31:0] SOC_PLL_CFG_REG;
wire [31:0] SOC_PLL_LOCK_REG;
wire [31:0] SOC_PLL_BP_REG;always@(posedge clk) beginif(psel & (~pwrite)) begincase(paddr)32'b00000000 + 32'h10 : prdata <= SOC_PLL_CFG_REG;32'b00000000 + 32'h14 : prdata <= SOC_PLL_LOCK_REG;32'b00000000 + 32'h18 : prdata <= SOC_PLL_BP_REG;default: prdata <= 32'hdeadbeaf;endcaseend
endassign SOC_PLL_CFG_REG[31:24] = 8'b0;
assign SOC_PLL_CFG_REG[23:12] = soc_pll_cfg_reg_rd;
assign SOC_PLL_CFG_REG[11:9] = soc_pll_postdiv1;
assign SOC_PLL_CFG_REG[8:6] = SOC_PLL0_postdiv2;
assign SOC_PLL_CFG_REG[5:0] = soc_pll_postdvi2;
從上面代碼可以看到 當 psel 為 高,且 pwrite 為 低的時候 去判斷 paddr 的地址對應哪個寄存器的地址,然后將該寄存器的值賦值給 prdata。
同時也可以看到,SOC_PLL_CFG_REG 位域中的各個值,來源于不同的信號。
APB 寫寄存器 RTL 代碼實現
reg_wr = psel & pwrite & penable;
reg_rd = psel & (~pwrite)
assign soc_pll_cfg_reg_wr = (paddr == 32'h00000000 + 32'h10) & reg_wr;
assign soc_pll_cfg_reg_rd = (paddr == 32'h00000000 + 32'h10) & reg_rd;always@(posedge clk or negedge rst_n) beginif(!rst_n) beginsoc_pll_cfg_reg_rd < 12'd57;endelse if (soc_pll_cfg_reg_wr) beginsoc_pll_cfg_reg_rd < pwdata[23:12];end
endalways@(posedge clk or negedge rst_n) beginif(!rst_n) beginsoc_pll_postdiv1 < 3'b0;endelse if (soc_pll_cfg_reg_wr) beginsoc_pll_postdiv1 < pwdata[11:9];end
endalways@(posedge clk or negedge rst_n) beginif(!rst_n) beginsoc_pll_postdiv2 < 3'b3;endelse if (soc_pll_cfg_reg_wr) beginsoc_pll_postdvi2 < pwdata[8:6];end
end
always@(posedge clk or negedge rst_n) beginif(!rst_n) beginsoc_pll_postdvi2 < 6'd4;endelse if (soc_pll_cfg_reg_wr) beginsoc_pll_postdvi2 < pwdata[5:0];end
end
從上面的代碼中可以看到,在寫 SOC_PLL_CFG_REG
這個寄存器的的時候需要先保證 soc_pll_cfg_reg_wr
這個信號為高,這個信號的作用是保證 寄存器的地址已經 APB 總線都準備好了之后才進行寫操作。