1. Preface
In the case of high real-time requirements, the way the CPU software is executed obviously can not meet the requirements, which requires hardware logic to implement some functions.For a custom IP core to be accessed by the CPU, it must have a bus interface.ZYNQ uses AXI BUS to achieve data interaction between PS and PL.This paper takes PWM as an example to design a custom AXI bus IP to demonstrate how to use the architecture of ARM+GA flexibly.
Function Definition: Add a custom IP core to the system explained in the previous entry ZYNQ example blog, whose output drives LED and so on to achieve respiratory lamp effect.And the software enables it by configuring registers, turns it on/off, and chooses the step of duty cycle change.In addition, the increase or decrease of the change step of duty cycle can be completed by key operation.
Platform: MIZ702N (ZYNQ-7020)
Software: VIVADO+SDK 2017
Note: Custom IP logic design uses Mingdeyang to Simplicity design method
2. PWM IP Design
PWM achieves its control purpose by controlling the duty cycle of the periodic pulse signal, that is, by changing the duration of the high level in a fixed period.Pulse cycles require a counter to be timed, and duty cycles from low to high and from high to low also require a counter to indicate, so two nested counters, cnt_cyc and cnt_mode, are used here.In addition to waiting for the cnt_cyc count to complete, the addition of a cnt_model also takes into account the change in the duty cycle.
You can use the position along the descending edge to indicate the duty cycle, and the closer the position is to the periodic value, the higher the duty cycle.In mode 0, the downward position increases in step until it is greater than or equal to the periodic value, while in mode 1, the downward position decreases in step until it is less than the step.Mode 0 and mode 1 are indicated using two signals up_stage and down_stage, respectively.As for the step value, it is updated when the configuration is valid, otherwise the default value is used.The module's final output signal is less than 1 along the cycle counter, and vice versa.Design complete, code:
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2020/03/01 18:14:44 7 // Design Name: 8 // Module Name: pwm 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 23 module pwm( 24 input clk,//Frequency 100 MHz 10ns 25 input rst_n, 26 input sw_en,//Output Enables 27 input sw_set_en,//Step settings enable 28 input [10-1:0] sw_freq_step,//Step value 29 output reg led 30 ); 31 32 parameter FREQ_STEP = 10'd100; 33 34 parameter CNT_CYC_MAX = 50000; 35 36 function integer clogb2 (input integer bit_depth); 37 begin 38 for(clogb2=0;bit_depth>0;clogb2=clogb2+1) 39 bit_depth = bit_depth >> 1; 40 end 41 endfunction 42 43 localparam CNT_CYC_WIDTH = clogb2(CNT_CYC_MAX-1); 44 45 46 reg [CNT_CYC_WIDTH-1:0] cnt_cyc=0; 47 wire add_cnt_cyc,end_cnt_cyc; 48 reg [2-1:0] cnt_mode=0; 49 wire add_cnt_mode,end_cnt_mode; 50 wire up_stage,down_stage; 51 reg [CNT_CYC_WIDTH+1-1:0] neg_loc=0; 52 reg [10-1:0] freq_step=FREQ_STEP; 53 54 55 //Cycle counter count 50 ms=50*1000ns = 50000_0ns 56 always@(posedge clk)begin 57 if(~rst_n)begin 58 cnt_cyc <= 0; 59 end 60 else if(add_cnt_cyc)begin 61 if(end_cnt_cyc) 62 cnt_cyc <= 0; 63 else 64 cnt_cyc <= cnt_cyc + 1'b1; 65 end 66 end 67 68 assign add_cnt_cyc = sw_en == 1; 69 assign end_cnt_cyc = add_cnt_cyc && cnt_cyc == CNT_CYC_MAX- 1; 70 71 //Mode counter 0-Duty cycle increment 1-Duty cycle decreases 72 always@(posedge clk)begin 73 if(~rst_n)begin 74 cnt_mode <= 0; 75 end 76 else if(add_cnt_mode)begin 77 if(end_cnt_mode) 78 cnt_mode <= 0; 79 else 80 cnt_mode <= cnt_mode + 1'b1; 81 end 82 end 83 84 assign add_cnt_mode = end_cnt_cyc && ((up_stage && neg_loc >= CNT_CYC_MAX) || (down_stage && neg_loc == 0)); 85 assign end_cnt_mode = add_cnt_mode && cnt_mode == 2 - 1; 86 87 88 //Change Step Settings 89 always@(posedge clk)begin 90 if(~rst_n)begin 91 freq_step <= FREQ_STEP; 92 end 93 else if(sw_set_en)begin 94 if(sw_freq_step >= 1 && sw_freq_step < 2000) 95 freq_step <= sw_freq_step; 96 else 97 freq_step <= FREQ_STEP; 98 end 99 end 100 101 //Pulse drop counter value along corresponding period 102 always@(posedge clk)begin 103 if(~rst_n)begin 104 neg_loc <= 0; 105 end 106 else if(end_cnt_cyc)begin 107 if(up_stage )begin//Duty Cycle Increasing Stage 108 if(neg_loc < CNT_CYC_MAX) 109 neg_loc <= neg_loc + freq_step; 110 end 111 else if(down_stage )begin//Duty Cycle Decreasing Stage 112 if(neg_loc < freq_step) 113 neg_loc <= 0; 114 else 115 neg_loc <= neg_loc - freq_step; 116 end 117 end 118 119 end 120 121 assign up_stage = add_cnt_cyc && cnt_mode == 0; 122 assign down_stage = add_cnt_cyc && cnt_mode == 1; 123 124 125 //output 126 always@(posedge clk)begin 127 if(~rst_n)begin 128 led <= 1'b0;//High level lighting 129 end 130 else if(add_cnt_cyc && cnt_cyc < neg_loc)begin 131 led <= 1'b1; 132 end 133 else 134 led <= 1'b0; 135 end 136 137 138 139 endmodulepwm.v