前面提到过,在传输结束后不要立即更改地址和写信号,保持当前状态直到开始下一个传输,这样可以降低功耗。这一篇给出另外一种方法,也就是使用门控时钟,来gete住PCLK,在没有寄存器配制的时候,把PCLK关掉,这样可以降低功耗。这个PCLKG也仅仅是在配制Slave的寄存器时候打开,其他时候关闭;在跟PCLKG同频同相的原始时钟PCLK,这个时钟是要一直输入给Slave模块的,因为Slave里面的内部逻辑需要这个时钟才能跑起来。
代码:APB4 Slave的门控时钟模块
module cmsdk_clock_gate#( parameter CLKGATE_PRESENT = 0) ( // 端口定义 input wire CLK, input wire CLKENABLE, //这个可以是由AHB2APB的bridge发过来的信号,代表有没有有效的APB transaction存在 input wire DISABLEG, output wire GATEDCLK_ERR, output wire GATEDCLK ); wire i_clk; wire clk_en; wire clk_en_t2; wire i_gated_clk; wire i_gated_clk_err; //使用的时候用i_gated_clk,不要用i_gated_clk_err,我只是用来测试的 wire mst_clk_en; wire mst_disable; assign GATEDCLK = (CLKGATE_PRESENT != 0)? i_gated_clk : 1'b0; assign GATEDCLK_ERR = (CLKGATE_PRESENT != 0)? i_gated_clk_err : 1'b0; assign mst_clk_en = (CLKGATE_PRESENT != 0)? CLKENABLE : 1'b0; assign mst_disable = (CLKGATE_PRESENT != 0)? DISABLEG : 1'b0; assign i_clk = (CLKGATE_PRESENT != 0)? CLK : 1'b0; assign clk_en = mst_clk_en | mst_disable; always @(i_clk or clk_en) begin if (i_clk == 1'b0) clk_en_t2 <= clk_en; end assign i_gated_clk = i_clk & clk_en_t2; assign i_gated_clk_err = i_clk & clk_en; endmodule
上面代码中有一个i_gated_clk_err信号,为什么要把clk_en打一拍?看下面的时序仿真图来理解。