Initial version of PWM / tach slave

parents
This diff is collapsed.
import os.path
__dir__ = os.path.split(os.path.abspath(os.path.realpath(__file__)))[0]
data_location = os.path.join(__dir__, "rtl")
src = "https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-litex/pythondata-peripheral-simplertc"
def data_file(f):
"""Get absolute path for file inside pythondata_cpu_simplertc."""
fn = os.path.join(data_location, f)
fn = os.path.abspath(fn)
if not os.path.exists(fn):
raise IOError("File {f} doesn't exist in pythondata_peripheral_simplertc".format(f))
return fn
// © 2020 - 2021 Raptor Engineering, LLC
//
// Released under the terms of the GPL v3
// See the LICENSE file for full details
// Stop LiteX silently ignoring net naming / missing register errors
`default_nettype none
module simple_pwm_wishbone #(
parameter BASE_CLOCK_FREQUENCY_KHZ = 50000,
parameter REQUIRED_PWM_FREQUENCY_KHZ = 25
)
(
// Wishbone slave port signals
input wire slave_wb_cyc,
input wire slave_wb_stb,
input wire slave_wb_we,
input wire [29:0] slave_wb_addr,
input wire [31:0] slave_wb_dat_w,
output wire [31:0] slave_wb_dat_r,
input wire [3:0] slave_wb_sel,
output wire slave_wb_ack,
output wire slave_wb_err,
input wire peripheral_reset,
input wire peripheral_clock,
input wire [31:0] slave_wb_dat_w,
input wire pwm_clock,
output wire pwm1_out,
output wire pwm2_out,
output wire pwm3_out,
output wire pwm4_out,
input wire tach1_in,
input wire tach2_in,
input wire tach3_in,
input wire tach4_in
);
// Control and status registers
wire [63:0] device_id;
wire [31:0] device_version;
reg [31:0] control_reg1 = 0;
wire [31:0] status_reg1;
wire [31:0] status_reg2;
// Device identifier
assign device_id = 64'h7c5250545350574d;
assign device_version = 32'h00010000;
reg slave_wb_ack_reg = 0;
reg [31:0] slave_wb_dat_r_reg = 0;
assign slave_wb_ack = slave_wb_ack_reg;
assign slave_wb_dat_r = slave_wb_dat_r_reg;
parameter MMIO_TRANSFER_STATE_IDLE = 0;
parameter MMIO_TRANSFER_STATE_TR01 = 1;
reg [31:0] mmio_buffer_address_reg = 0;
reg [7:0] mmio_transfer_state = 0;
reg [31:0] mmio_cfg_space_tx_buffer = 0;
reg [31:0] mmio_cfg_space_rx_buffer = 0;
// Wishbone connector
always @(posedge peripheral_clock) begin
if (peripheral_reset) begin
// Reset Wishbone interface / control state machine
slave_wb_ack_reg <= 0;
mmio_transfer_state <= MMIO_TRANSFER_STATE_IDLE;
end else begin
case (mmio_transfer_state)
MMIO_TRANSFER_STATE_IDLE: begin
// Compute effective address
mmio_buffer_address_reg[31:2] = slave_wb_addr;
case (slave_wb_sel)
4'b0001: mmio_buffer_address_reg[1:0] = 0;
4'b0010: mmio_buffer_address_reg[1:0] = 1;
4'b0100: mmio_buffer_address_reg[1:0] = 2;
4'b1000: mmio_buffer_address_reg[1:0] = 3;
4'b1111: mmio_buffer_address_reg[1:0] = 0;
default: mmio_buffer_address_reg[1:0] = 0;
endcase
if (slave_wb_cyc && slave_wb_stb) begin
// Configuration register space access
// Single clock pulse signals in deasserted state...process incoming request!
if (!slave_wb_we) begin
// Read requested
case ({mmio_buffer_address_reg[7:2], 2'b00})
0: mmio_cfg_space_tx_buffer = device_id[63:32];
4: mmio_cfg_space_tx_buffer = device_id[31:0];
8: mmio_cfg_space_tx_buffer = device_version;
12: mmio_cfg_space_tx_buffer = control_reg1;
16: mmio_cfg_space_tx_buffer = status_reg1;
20: mmio_cfg_space_tx_buffer = status_reg2;
default: mmio_cfg_space_tx_buffer = 0;
endcase
// Endian swap
slave_wb_dat_r_reg[31:24] <= mmio_cfg_space_tx_buffer[7:0];
slave_wb_dat_r_reg[23:16] <= mmio_cfg_space_tx_buffer[15:8];
slave_wb_dat_r_reg[15:8] <= mmio_cfg_space_tx_buffer[23:16];
slave_wb_dat_r_reg[7:0] <= mmio_cfg_space_tx_buffer[31:24];
// Signal transfer complete
slave_wb_ack_reg <= 1;
mmio_transfer_state <= MMIO_TRANSFER_STATE_TR01;
end else begin
// Write requested
case ({mmio_buffer_address_reg[7:2], 2'b00})
// Device ID / version registers cannot be written, don't even try...
12: mmio_cfg_space_rx_buffer = control_reg1;
// Status registers cannot be written, don't even try...
default: mmio_cfg_space_rx_buffer = 0;
endcase
if (slave_wb_sel[0]) begin
mmio_cfg_space_rx_buffer[7:0] = slave_wb_dat_w[31:24];
end
if (slave_wb_sel[1]) begin
mmio_cfg_space_rx_buffer[15:8] = slave_wb_dat_w[23:16];
end
if (slave_wb_sel[2]) begin
mmio_cfg_space_rx_buffer[23:16] = slave_wb_dat_w[15:8];
end
if (slave_wb_sel[3]) begin
mmio_cfg_space_rx_buffer[31:24] = slave_wb_dat_w[7:0];
end
case ({mmio_buffer_address_reg[7:2], 2'b00})
12: control_reg1 <= mmio_cfg_space_rx_buffer;
endcase
// Signal transfer complete
slave_wb_ack_reg <= 1;
mmio_transfer_state <= MMIO_TRANSFER_STATE_TR01;
end
end
end
MMIO_TRANSFER_STATE_TR01: begin
// Cycle complete
slave_wb_ack_reg <= 0;
mmio_transfer_state <= MMIO_TRANSFER_STATE_IDLE;
end
default: begin
// Should never reach this state
mmio_transfer_state <= MMIO_TRANSFER_STATE_IDLE;
end
endcase
end
end
// Instantiate simple PWM modules and connect signals
wire [15:0] tach1_count;
simple_pwm #(
.BASE_CLOCK_FREQUENCY_KHZ(BASE_CLOCK_FREQUENCY_KHZ),
.REQUIRED_PWM_FREQUENCY_KHZ(REQUIRED_PWM_FREQUENCY_KHZ),
.PWM_CTL_BITS(8),
.TACH_COUNT_BITS(16)
) simple_pwm_1(
.base_clock(pwm_clock),
.pwm_set(control_reg1[7:0]),
.pwm_out(pwm1_out),
.tach_count(tach1_count),
.tach_in(tach1_in)
);
wire [15:0] tach2_count;
simple_pwm #(
.BASE_CLOCK_FREQUENCY_KHZ(BASE_CLOCK_FREQUENCY_KHZ),
.REQUIRED_PWM_FREQUENCY_KHZ(REQUIRED_PWM_FREQUENCY_KHZ),
.PWM_CTL_BITS(8),
.TACH_COUNT_BITS(16)
) simple_pwm_2(
.base_clock(pwm_clock),
.pwm_set(control_reg1[15:8]),
.pwm_out(pwm2_out),
.tach_count(tach2_count),
.tach_in(tach2_in)
);
wire [15:0] tach3_count;
simple_pwm #(
.BASE_CLOCK_FREQUENCY_KHZ(BASE_CLOCK_FREQUENCY_KHZ),
.REQUIRED_PWM_FREQUENCY_KHZ(REQUIRED_PWM_FREQUENCY_KHZ),
.PWM_CTL_BITS(8),
.TACH_COUNT_BITS(16)
) simple_pwm_3(
.base_clock(pwm_clock),
.pwm_set(control_reg1[23:16]),
.pwm_out(pwm3_out),
.tach_count(tach3_count),
.tach_in(tach3_in)
);
wire [15:0] tach4_count;
simple_pwm #(
.BASE_CLOCK_FREQUENCY_KHZ(BASE_CLOCK_FREQUENCY_KHZ),
.REQUIRED_PWM_FREQUENCY_KHZ(REQUIRED_PWM_FREQUENCY_KHZ),
.PWM_CTL_BITS(8),
.TACH_COUNT_BITS(16)
) simple_pwm_4(
.base_clock(pwm_clock),
.pwm_set(control_reg1[31:24]),
.pwm_out(pwm4_out),
.tach_count(tach4_count),
.tach_in(tach4_in)
);
assign status_reg1[15:8] = tach1_count;
assign status_reg1[31:16] = tach2_count;
assign status_reg2[15:8] = tach3_count;
assign status_reg2[31:16] = tach4_count;
endmodule
module simple_pwm #(
parameter BASE_CLOCK_FREQUENCY_KHZ = 100000,
parameter REQUIRED_PWM_FREQUENCY_KHZ = 25,
parameter TACHOMETER_SAMPLE_RATE_HZ = 5,
parameter PWM_CTL_BITS = 8,
parameter TACH_COUNT_BITS = 16
)
(
input wire base_clock,
input wire [PWM_CTL_BITS-1:0] pwm_set,
output wire pwm_out,
output wire [TACH_COUNT_BITS-1:0] tach_count,
input wire tach_in
);
reg pwm_out_reg = 0;
assign pwm_out = pwm_out_reg;
reg [PWM_CTL_BITS-1:0] tach_count_reg = 0;
assign tach_count = tach_count_reg;
reg [PWM_CTL_BITS-1:0] pwm_counter = 0;
reg [TACH_COUNT_BITS-1:0] tach_counter = 0;
reg tach_in_prev = 0;
reg tach_in_reg = 0;
reg [15:0] pwm_clock_div_counter;
reg [23:0] tach_clock_div_counter;
always @(posedge base_clock) begin
if (pwm_clock_div_counter > ((BASE_CLOCK_FREQUENCY_KHZ / REQUIRED_PWM_FREQUENCY_KHZ) / (2 ** PWM_CTL_BITS))) begin
if (pwm_counter < pwm_set) begin
pwm_out_reg <= 1;
end else begin
pwm_out_reg <= 0;
end
pwm_clock_div_counter <= 0;
end else begin
pwm_clock_div_counter <= pwm_clock_div_counter + 1;
end
end
always @(posedge base_clock) begin
if (tach_clock_div_counter > (BASE_CLOCK_FREQUENCY_KHZ / TACHOMETER_SAMPLE_RATE_HZ)) begin
tach_count_reg <= tach_counter;
tach_counter <= 0;
tach_clock_div_counter <= 0;
end else begin
if ((tach_in_prev == 1) && (tach_in_reg == 0)) begin
tach_counter <= tach_counter + 1;
end
tach_clock_div_counter <= tach_clock_div_counter + 1;
end
tach_in_prev <= tach_in_reg;
tach_in_reg <= tach_in;
end
endmodule
#!/usr/bin/env python3
from setuptools import setup
from setuptools import find_packages
setup(
name="pythondata-peripheral-simplepwm",
description="Verilog files for Simple PWM module",
author="Raptor Engineering, LLC",
author_email="support@raptorengineering.com",
url="https://www.raptorengineering.com",
download_url="https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-litex/pythondata-peripheral-simplepwm",
test_suite="test",
license="GPLv3",
python_requires="~=3.6",
packages=find_packages(exclude=("test*", "sim*", "doc*", "examples*")),
include_package_data=True,
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment