Zynq Pwm

优质blog

状态设计之我见:

我从你的分析视角看到了我之前缺略的一个思路,就是很好的区分了边界和状态。简而言之,边界之间是状态。然而对于一般的设计,边界是易于表达的,而状态是易于理解的。以周期的计算来说,边界就是counter这个计数器构成了0,1,2—n-1这个n个边界点,其中存在突变点m。但是边界点却不能直观看出时间,我们将两个边界之间的点定义为状态。一般来说,每个状态的参数是相同的(比如每个状态的时间).然后我们就去计算我们要去讨论的大状态包含的基状态,比如一个周期包含的基状态,一个周期中上升沿包含的基状态。而基状态的研究只需要看大状态对应的边界点就行了

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//pwm.sv
// 1个端口控制输出pwm的周期,3个输入端口分别控制3个输出端口的占空比
module pwm (
    input logic clk,
    input logic [15:0] period,
    input logic [15:0] duty1,
    input logic [15:0] duty2,
    input logic [15:0] duty3,
    input logic rst,
    output logic pwm1,
    output logic pwm2,
    output logic pwm3
);

  logic [15:0] counter = 0;
  always_ff @(posedge clk, negedge rst) begin : pwm_block
    if (!rst) begin
      counter <= 0;
    end else begin
      if (counter < period - 1) counter <= counter + 1;
      else counter <= 0;
      //pmw1
    end
  end
  always_comb begin
    if (counter < duty1) begin
      pwm1 = 0;
    end else begin
      pwm1 = 1;
    end

    if (counter < duty2) begin
      pwm2 = 0;
    end else begin
      pwm2 = 1;
    end


    if (counter < duty3) begin
      pwm3 = 0;
    end else begin
      pwm3 = 1;
    end


  end
endmodule
// 注:这个代码写的并不规范,应该把组合逻辑部分放到时序部分变成同步更新,减少毛刺
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//tb_pwm.sv
module tb_pwm ();
  parameter real CLK_PERIOD = 10;  //假设时钟周期为10ns
  logic clk;
  logic [15:0] period;
  logic [15:0] duty1;
  logic [15:0] duty2;
  logic [15:0] duty3;
  logic rst;
  logic pwm1;
  logic pwm2;
  logic pwm3;
  pwm dut_pwm (
      .clk(clk),
      .period(period),
      .duty1(duty1),
      .duty2(duty2),
      .duty3(duty3),
      .rst(rst),
      .pwm1(pwm1),
      .pwm2(pwm2),
      .pwm3(pwm3)
  );

  initial begin
    clk = 0;
   end
  always begin
    #(CLK_PERIOD / 2) clk = ~clk;
  end

  initial begin
    rst = 1;
    @(posedge clk);
    period = 10;
    duty1 = 2;
    duty2 = 4;
    duty3 = 6;
    repeat (1000) @(posedge clk) ;
    $finish;
  end
endmodule

PS 代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//ps 端通过uart控制占空比
//ps 端通过uart控制占空比
#include "xparameters.h"
#include "xil_io.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
#include "xuartlite_i.h"

#define period_offset 0x00
#define duty1_offset 0x04
#define duty2_offset 0x08
#define duty3_offset 0x0c
int main(void){

   //uartlite
   XUartLite uartlite0;
   XUartLite_Initialize(&uartlite0,XPAR_XUARTLITE_0_BASEADDR);
   u8 recv_package[8];
   u8 send_package[8]={'i','n'};
   //XUartLite_Send(&uartlite0,send_package,2);
   // T=period/fclk
   // 由于设计失误,duty1,2,3分别表示一个周期内低电平的状态数

   u32 period=1000;
   u32 duty1=600;
   u32 duty2=400;
   u32 duty3=200;
   Xil_Out32(XPAR_PWM_IP_0_BASEADDR+period_offset,period);
   Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty1_offset,duty1);
   Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty2_offset,duty2);
   Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty3_offset,duty3);
   while(1)
   {  
      XUartLite_Send(&uartlite0,send_package,2);
       //XUartLite_Send(&uartlite0,send_package,2);
      recv_package[0]=XUartLite_RecvByte(XPAR_XUARTLITE_0_BASEADDR);
      XUartLite_Send(&uartlite0,send_package,2);
      recv_package[1]=XUartLite_RecvByte(XPAR_XUARTLITE_0_BASEADDR);
      recv_package[2]=XUartLite_RecvByte(XPAR_XUARTLITE_0_BASEADDR);
      //XUartLite_Recv(&uartlite0,recv_package,3);
       XUartLite_Send(&uartlite0,send_package,2);
      u32 sum=10*(recv_package[1]-'0')+(recv_package[2]-'0');
      u32 duty=period-period*sum/100;
      if(recv_package[0]=='1')
      {
         duty1=duty;
         Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty1_offset,duty1);
      }

      else if(recv_package[0]=='2')
      {
         duty2=duty;
         Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty2_offset,duty2);
      }
      else
      {
         duty3=duty;
         Xil_Out32(XPAR_PWM_IP_0_BASEADDR+duty3_offset,duty3);
      }
   }
}

AXI

Built with Hugo
Theme Stack designed by Jimmy