简易寄存器接口SMMR---pwm控制器
参考简易寄存器接口SMMR的vio_uart桥接.csdn简易寄存器接口SMMR.csdn可配置的PWM外设模块.csdnpwm_slot.vtimescale 1ns / 1ps module pwm_slot #( parameter P_ADDR_WIDTH 8, parameter P_DATA_WIDTH 32, parameter [P_ADDR_WIDTH-1:0] P_SLOT_BASE 0, parameter P_REG_COUNT 32, parameter P_NUM_PWM 1, parameter P_COUNTER_WIDTH 32, parameter [P_COUNTER_WIDTH-1:0] P_DEFAULT_PERIOD 4096 )( input wire i_clk, input wire i_rst_n, // // SMMR // input wire i_reg_wr_en, input wire [P_ADDR_WIDTH-1:0] i_reg_wr_addr, input wire [P_DATA_WIDTH-1:0] i_reg_wr_data, input wire [P_ADDR_WIDTH-1:0] i_reg_rd_addr, output reg [P_DATA_WIDTH-1:0] o_reg_rd_data, // // PWM output // output wire [P_NUM_PWM-1:0] o_pwm ); //////////////////////////////////////////////////////////////////////////// // PWM SLOT Register Map //////////////////////////////////////////////////////////////////////////// localparam [P_ADDR_WIDTH-1:0] ADDR_CONTROL P_SLOT_BASE 9d0; // 控制寄存器 bit0: enable localparam [P_ADDR_WIDTH-1:0] ADDR_STATUS P_SLOT_BASE 9d1; // 状态寄存器 bit0: param_error localparam [P_ADDR_WIDTH-1:0] ADDR_PERIOD P_SLOT_BASE 9d2; // PWM周期 localparam [P_ADDR_WIDTH-1:0] ADDR_DUTY0 P_SLOT_BASE 9d16; // PWM0占空比 localparam [P_ADDR_WIDTH-1:0] ADDR_DUTY_MAX P_SLOT_BASE 9d31; // 最大PWM通道地址 //////////////////////////////////////////////////////////////////////////// // Register //////////////////////////////////////////////////////////////////////////// reg [P_DATA_WIDTH-1:0] r_ctrl; reg [P_DATA_WIDTH-1:0] r_period; reg [P_DATA_WIDTH-1:0] r_duty [0:P_NUM_PWM-1]; reg [P_DATA_WIDTH-1:0] r_status; //////////////////////////////////////////////////////////////////////////// // PWM runtime //////////////////////////////////////////////////////////////////////////// reg [P_COUNTER_WIDTH-1:0] r_cnt; reg [P_COUNTER_WIDTH-1:0] r_period_latch; reg [P_COUNTER_WIDTH-1:0] r_duty_latch [0:P_NUM_PWM-1]; integer i; //////////////////////////////////////////////////////////////////////////// // SMMR WRITE //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_ctrl 0; r_period P_DEFAULT_PERIOD; for(i0;iP_NUM_PWM;ii1) r_duty[i] 0; end else begin if(i_reg_wr_en) begin case(i_reg_wr_addr) ADDR_CONTROL: r_ctrl i_reg_wr_data; ADDR_PERIOD: r_period i_reg_wr_data; default: for(i0;iP_NUM_PWM;ii1) if(i_reg_wr_addr (ADDR_DUTY0i)) r_duty[i] i_reg_wr_data; endcase end end end //////////////////////////////////////////////////////////////////////////// // STATUS //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_status 0; else begin r_status[0] (r_period0); end end //////////////////////////////////////////////////////////////////////////// // Period counter //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_cnt 0; r_period_latch P_DEFAULT_PERIOD; end else if(r_ctrl[0]) begin if(r_cnt r_period_latch-1) begin r_cnt 0; r_period_latch r_period; for(i0;iP_NUM_PWM;ii1) r_duty_latch[i] r_duty[i]; end else r_cnt r_cnt 1b1; end else begin r_cnt 0; r_period_latch r_period; for(i0;iP_NUM_PWM;ii1) r_duty_latch[i] r_duty[i]; end end //////////////////////////////////////////////////////////////////////////// // SMMR READ //////////////////////////////////////////////////////////////////////////// always (*) begin o_reg_rd_data 0; if((i_reg_rd_addr P_SLOT_BASE) (i_reg_rd_addr P_SLOT_BASEP_REG_COUNT)) begin case(i_reg_rd_addr) ADDR_CONTROL: o_reg_rd_data r_ctrl; ADDR_STATUS: o_reg_rd_data r_status; ADDR_PERIOD: o_reg_rd_data r_period; default: for(i0;iP_NUM_PWM;ii1) if(i_reg_rd_addr (ADDR_DUTY0i)) o_reg_rd_data r_duty[i]; endcase end end //////////////////////////////////////////////////////////////////////////// // PWM output //////////////////////////////////////////////////////////////////////////// genvar g; generate for(g0;gP_NUM_PWM;gg1) begin : GEN_PWM assign o_pwm[g] (r_ctrl[0] (r_cnt r_duty_latch[g]))? 1b1: 1b0; end endgenerate endmoduletb_pwm_slot.vpwm0 占空比 50% pwm1 占空比 20%timescale 1ns / 1ps module pwm_slot #( parameter P_ADDR_WIDTH 8, parameter P_DATA_WIDTH 32, parameter [P_ADDR_WIDTH-1:0] P_SLOT_BASE 0, parameter P_REG_COUNT 32, parameter P_NUM_PWM 1, parameter P_COUNTER_WIDTH 32, parameter [P_COUNTER_WIDTH-1:0] P_DEFAULT_PERIOD 4096 )( input wire i_clk, input wire i_rst_n, // // SMMR // input wire i_reg_wr_en, input wire [P_ADDR_WIDTH-1:0] i_reg_wr_addr, input wire [P_DATA_WIDTH-1:0] i_reg_wr_data, input wire [P_ADDR_WIDTH-1:0] i_reg_rd_addr, output reg [P_DATA_WIDTH-1:0] o_reg_rd_data, // // PWM output // output wire [P_NUM_PWM-1:0] o_pwm ); //////////////////////////////////////////////////////////////////////////// // PWM SLOT Register Map //////////////////////////////////////////////////////////////////////////// localparam [P_ADDR_WIDTH-1:0] ADDR_CONTROL P_SLOT_BASE 9d0; // 控制寄存器 bit0: enable localparam [P_ADDR_WIDTH-1:0] ADDR_STATUS P_SLOT_BASE 9d1; // 状态寄存器 bit0: param_error localparam [P_ADDR_WIDTH-1:0] ADDR_PERIOD P_SLOT_BASE 9d2; // PWM周期 localparam [P_ADDR_WIDTH-1:0] ADDR_DUTY0 P_SLOT_BASE 9d16; // PWM0占空比 localparam [P_ADDR_WIDTH-1:0] ADDR_DUTY_MAX P_SLOT_BASE 9d31; // 最大PWM通道地址 //////////////////////////////////////////////////////////////////////////// // Register //////////////////////////////////////////////////////////////////////////// reg [P_DATA_WIDTH-1:0] r_ctrl; reg [P_DATA_WIDTH-1:0] r_period; reg [P_DATA_WIDTH-1:0] r_duty [0:P_NUM_PWM-1]; reg [P_DATA_WIDTH-1:0] r_status; //////////////////////////////////////////////////////////////////////////// // PWM runtime //////////////////////////////////////////////////////////////////////////// reg [P_COUNTER_WIDTH-1:0] r_cnt; reg [P_COUNTER_WIDTH-1:0] r_period_latch; reg [P_COUNTER_WIDTH-1:0] r_duty_latch [0:P_NUM_PWM-1]; integer i; //////////////////////////////////////////////////////////////////////////// // SMMR WRITE //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_ctrl 0; r_period P_DEFAULT_PERIOD; for(i0;iP_NUM_PWM;ii1) r_duty[i] 0; end else begin if(i_reg_wr_en) begin case(i_reg_wr_addr) ADDR_CONTROL: r_ctrl i_reg_wr_data; ADDR_PERIOD: r_period i_reg_wr_data; default: for(i0;iP_NUM_PWM;ii1) if(i_reg_wr_addr (ADDR_DUTY0i)) r_duty[i] i_reg_wr_data; endcase end end end //////////////////////////////////////////////////////////////////////////// // STATUS //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_status 0; else begin r_status[0] (r_period0); end end //////////////////////////////////////////////////////////////////////////// // Period counter //////////////////////////////////////////////////////////////////////////// always (posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_cnt 0; r_period_latch P_DEFAULT_PERIOD; end else if(r_ctrl[0]) begin if(r_cnt r_period_latch-1) begin r_cnt 0; r_period_latch r_period; for(i0;iP_NUM_PWM;ii1) r_duty_latch[i] r_duty[i]; end else r_cnt r_cnt 1b1; end else begin r_cnt 0; r_period_latch r_period; for(i0;iP_NUM_PWM;ii1) r_duty_latch[i] r_duty[i]; end end //////////////////////////////////////////////////////////////////////////// // SMMR READ //////////////////////////////////////////////////////////////////////////// always (*) begin o_reg_rd_data 0; if((i_reg_rd_addr P_SLOT_BASE) (i_reg_rd_addr P_SLOT_BASEP_REG_COUNT)) begin case(i_reg_rd_addr) ADDR_CONTROL: o_reg_rd_data r_ctrl; ADDR_STATUS: o_reg_rd_data r_status; ADDR_PERIOD: o_reg_rd_data r_period; default: for(i0;iP_NUM_PWM;ii1) if(i_reg_rd_addr (ADDR_DUTY0i)) o_reg_rd_data r_duty[i]; endcase end end //////////////////////////////////////////////////////////////////////////// // PWM output //////////////////////////////////////////////////////////////////////////// genvar g; generate for(g0;gP_NUM_PWM;gg1) begin : GEN_PWM assign o_pwm[g] (r_ctrl[0] (r_cnt r_duty_latch[g]))? 1b1: 1b0; end endgenerate endmodule测试输出run all READaddr0data00000001 READaddr1data00000000 READaddr2data000003e8 READaddr16data000000c8 READaddr17data000001f4