| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| { |
| name: "pwm", |
| human_name: "Pulse Width Modulator", |
| one_line_desc: "Transmission of pulse-width modulated output signals with adjustable duty cycle", |
| one_paragraph_desc: ''' |
| Pulse Width Modulator creates pulse-width modulated (PWM) signals with adjustable duty cycle. |
| It is suitable for general-purpose use, but primarily designed for control of LEDs. |
| All outputs are programmable with frequency, phase, and duty cycle. |
| ''' |
| design_spec: "../doc", |
| dv_doc: "../doc/dv", |
| hw_checklist: "../doc/checklist", |
| sw_checklist: "/sw/device/lib/dif/dif_pwm", |
| revisions: [ |
| { |
| version: "1.0", |
| life_stage: "L1", |
| design_stage: "D2S", |
| verification_stage: "V2S", |
| dif_stage: "S2", |
| notes: "" |
| } |
| ] |
| clocking: [ |
| {clock: "clk_i", reset: "rst_ni", primary: true}, |
| {clock: "clk_core_i", reset: "rst_core_ni"} |
| ] |
| bus_interfaces: [ |
| { protocol: "tlul", direction: "device" } |
| ], |
| regwidth: "32", |
| param_list: [ |
| { name: "NOutputs", |
| desc: "Number of PWM outputs", |
| type: "int", |
| default: "6", |
| } |
| ] |
| available_output_list: [ |
| { name: "pwm" |
| desc: '''Pulse output. Note that though this output is always enabled, there is a formal |
| set of enable pins (pwm_en_o) which are required for top-level integration of |
| comportable IPs.''' |
| width: "6" |
| } |
| ] |
| alert_list: [ |
| { name: "fatal_fault", |
| desc: ''' |
| This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected. |
| ''' |
| } |
| ], |
| countermeasures: [ |
| { name: "BUS.INTEGRITY", |
| desc: "End-to-end bus integrity scheme." |
| } |
| ] |
| registers: [ |
| { name: "REGWEN", |
| desc: "Register write enable for all control registers", |
| swaccess: "rw0c", |
| hwaccess: "none", |
| fields: [ |
| { bits: "0", |
| desc: ''' When true, all writable registers can be modified. |
| When false, they become read-only. Defaults true, write |
| zero to clear. This can be cleared after initial |
| configuration at boot in order to lock in the listed |
| register settings.''' |
| resval: 1 |
| } |
| ] |
| } |
| { name: "CFG", |
| desc: "Configuration register", |
| swaccess: "rw", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "31", |
| name: "CNTR_EN", |
| desc: '''Assert this bit to enable the PWM phase counter. |
| Clearing this bit disables and resets the phase counter.''' |
| resval: "0x0" |
| }, |
| { bits: "30:27", |
| name: "DC_RESN" |
| desc: '''Phase Resolution (logarithmic). All duty-cycle and phase |
| shift registers represent fractional PWM cycles, expressed in |
| units of 2^16 PWM cycles. Each PWM cycle is divided |
| into 2^(DC_RESN+1) time slices, and thus only the (DC_RESN+1) |
| most significant bits of each phase or duty cycle register |
| are relevant.''' |
| resval: 7 |
| }, |
| { bits: "26:0", |
| name: "CLK_DIV", |
| desc: '''Sets the period of each PWM beat to be (CLK_DIV+1) |
| input clock periods. Since PWM pulses are generated once |
| every 2^(DC_RESN+1) beats, the period between output |
| pulses is 2^(DC_RESN+1)*(CLK_DIV+1) times longer than the |
| input clock period.''' |
| resval: "0x00008000" |
| } |
| ] |
| }, |
| { multireg: { name: "PWM_EN", |
| desc: "Enable PWM operation for each channel", |
| count: "NOutputs", |
| swaccess: "rw", |
| cname: "pwm_en", |
| compact: "1", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "0", |
| name: "EN", |
| desc: '''Write 1 to this bit to enable PWM pulses on the |
| corresponding channel.''', |
| resval: "0" |
| } |
| ] |
| } |
| }, |
| { multireg: { name: "INVERT", |
| desc: "Invert the PWM output for each channel", |
| count: "NOutputs", |
| swaccess: "rw", |
| cname: "pwm_invert", |
| compact: "1", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "0", |
| name: "INVERT", |
| desc: '''Write 1 to this bit to invert the output for each channel, |
| so that the corresponding output is active-low.''', |
| resval: "0" |
| } |
| ] |
| } |
| }, |
| { multireg: { name: "PWM_PARAM", |
| desc: "Basic PWM Channel Parameters", |
| count: "NOutputs" |
| swaccess: "rw", |
| cname: "pwm_params", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "31", |
| name: "BLINK_EN", |
| desc: '''Enables blink (or heartbeat). If cleared, the output duty |
| cycle will remain constant at DUTY_CYCLE.A. Enabling this |
| bit causes the PWM duty cycle to fluctuate between |
| DUTY_CYCLE.A and DUTY_CYCLE.B''' |
| resval: 0 |
| }, |
| { bits: "30", |
| name: "HTBT_EN", |
| desc: '''Modulates blink behavior to create a heartbeat effect. When |
| HTBT_EN is set, the duty cycle increases (or decreases) |
| linearly from DUTY_CYCLE.A to DUTY_CYCLE.B and back, in |
| steps of (BLINK_PARAM.Y+1), with an increment (decrement) |
| once every (BLINK_PARAM.X+1) PWM cycles. When HTBT_EN is |
| cleared, the standard blink behavior applies, meaning that |
| the output duty cycle alternates between DUTY_CYCLE.A for |
| (BLINK_PARAM.X+1) pulses and DUTY_CYCLE.B for |
| (BLINK_PARAM.Y+1) pulses.''' |
| resval: 0 |
| }, |
| { bits: "15:0", |
| name: "PHASE_DELAY", |
| desc: '''Phase delay of the PWM rising edge, in units of 2^(-16) PWM |
| cycles''', |
| resval: "0x0000" |
| } |
| ] |
| } |
| }, |
| { multireg: { name: "DUTY_CYCLE", |
| desc:'''Controls the duty_cycle of each channel.''', |
| count: "NOutputs" |
| swaccess: "rw", |
| cname: "duty_cycle", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "31:16", |
| name: "B", |
| desc: '''The target duty cycle for PWM output, in units |
| of 2^(-16)ths of a pulse cycle. The actual precision is |
| however limited to the (DC_RESN+1) most significant bits. |
| This setting only applies when blinking, and determines |
| the target duty cycle. |
| ''' |
| resval: "0x7fff" |
| } |
| { bits: "15:0", |
| name: "A", |
| desc: '''The initial duty cycle for PWM output, in units |
| of 2^(-16)ths of a pulse cycle. The actual precision is |
| however limited to the (DC_RESN+1) most significant bits. |
| This setting applies continuously when not blinking |
| and determines the initial duty cycle when blinking. |
| ''' |
| resval: "0x7fff" |
| } |
| ] |
| } |
| }, |
| { multireg: { name: "BLINK_PARAM", |
| desc: "Hardware controlled blink/heartbeat parameters.", |
| count: "NOutputs" |
| swaccess: "rw", |
| cname: "blink_param", |
| async: "clk_core_i", |
| hwqe: "true", |
| regwen: "REGWEN", |
| fields: [ |
| { bits: "15:0", |
| name: "X", |
| desc: '''This blink-rate timing parameter has two different |
| interpretations depending on whether or not the heartbeat |
| feature is enabled. If heartbeat is disabled, a blinking |
| PWM will pulse at duty cycle A for (X+1) pulses before |
| switching to duty cycle B. If heartbeat is enabled |
| the duty-cycle will start at the duty cycle A, but |
| will be incremented (or decremented) every (X+1) cycles. |
| In heartbeat mode is enabled, the size of each step is |
| controlled by BLINK_PARAM.Y.''' |
| resval: "0x00" |
| } |
| { bits: "31:16", |
| name: "Y", |
| desc: '''This blink-rate timing parameter has two different |
| interpretations depending on whether or not the heartbeat |
| feature is enabled. If heartbeat is disabled, a blinking |
| PWM will pulse at duty cycle B for (Y+1) pulse cycles |
| before returning to duty cycle A. If heartbeat is enabled |
| the duty cycle will increase (or decrease) by (Y+1) units |
| every time it is incremented (or decremented)''' |
| resval: "0x0" |
| } |
| ] |
| } |
| } |
| ] |
| } |