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) begin
if(psel & (~pwrite)) begin
case(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;
endcase
end
end
assign 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) begin
if(!rst_n) begin
soc_pll_cfg_reg_rd < 12'd57;
end
else if (soc_pll_cfg_reg_wr) begin
soc_pll_cfg_reg_rd < pwdata[23:12];
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
soc_pll_postdiv1 < 3'b0;
end
else if (soc_pll_cfg_reg_wr) begin
soc_pll_postdiv1 < pwdata[11:9];
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
soc_pll_postdiv2 < 3'b3;
end
else if (soc_pll_cfg_reg_wr) begin
soc_pll_postdvi2 < pwdata[8:6];
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
soc_pll_postdvi2 < 6'd4;
end
else if (soc_pll_cfg_reg_wr) begin
soc_pll_postdvi2 < pwdata[5:0];
end
end
从上面的代码中可以看到,在写 SOC_PLL_CFG_REG
这个寄存器的的时候需要先保证 soc_pll_cfg_reg_wr
这个信号为高,这个信号的作用是保证 寄存器的地址已经 APB 总线都准备好了之后才进行写操作。