Project SoC PWM
Project SoC PWM
UNIVERSITY OF SCIENCE
FACULTY OF ELECTRONICS AND TELECOMMUNICATIONS
SoC Lab
FINAL PROJECT
PULSE WIDTH MODULATION (PWM)
Lecture : MSc. Trần Tuấn Kiệt
Student : 20200017 Nguyễn Thành Đạt
: 20200018 Phan Thị Diễm
: 20200085 Nguyễn Văn Thành
: 20200110 Nguyễn Huy Trường
: 20200295 Tôn Nữ Tâm Nhi
: 20200353 Nguyễn Tiến Thông
Top module
A Pulse Width Modulation (PWM) module with adjustable parameters for duty
cycle, frequency, alignment, and counter mode. Additionally, it includes a Timer
Prescaler module responsible for counting and generating the PWM signal.
Code:
module PWM #(
parameter DATA_WIDTH = 32,
parameter DUTY_CYCLE_WIDTH = 7,
parameter SOURCE_CLOCK_VALUE = 50000000,
parameter ADDRESS_WIDTH = 1,
parameter PRES_WIDTH = 16,
parameter PERIOD_WIDTH = 16,
parameter COUNTER_WIDTH = 26
)(
input i_clk,
input i_reset,
input i_enable,
input i_wenable,
input [ADDRESS_WIDTH - 1 : 0] i_address,
input i_renable,
input [DATA_WIDTH - 1 : 0] i_data, //dyty cycle's
unit is %
output logic [DATA_WIDTH - 1 : 0] o_pwm_pulse
);
Timer_Prescaler #(
.DATA_WIDTH(DATA_WIDTH),
.SOURCE_CLOCK_VALUE(SOURCE_CLOCK_VALUE),
.PRES_WIDTH(PRES_WIDTH),
.PERIOD_WIDTH(PERIOD_WIDTH),
.DUTY_CYCLE_WIDTH(DUTY_CYCLE_WIDTH),
.ALIGNMENT_WIDTH(ALIGNMENT_WIDTH),
.CNTMODE_WIDTH(CNTMODE_WIDTH)
) Pres (
.i_clk_source(i_clk),
.i_reset(i_reset),
.i_CS(prescaler_enable),
.i_alignment(alignment_mode),
.i_countermode(counter_mode),
.i_prescaler(prescaler),
.i_period(period),
.i_dutycycle(duty_cycle),
.o_pwm_clk(pwm_out)
);
endmodule
module Timer_Prescaler #(
parameter DATA_WIDTH = 32,
parameter SOURCE_CLOCK_VALUE = 50000000,
parameter PRES_WIDTH = 16,
parameter PERIOD_WIDTH = 16,
parameter DUTY_CYCLE_WIDTH = 7,
parameter ALIGNMENT_WIDTH = 2,
parameter CNTMODE_WIDTH = 1,
parameter COUNTER_WIDTH = 26
)(
input i_clk_source,
input i_reset,
input i_CS,
input [ALIGNMENT_WIDTH - 1 : 0] i_alignment,
input [CNTMODE_WIDTH - 1 : 0] i_countermode,
input [PRES_WIDTH - 1:0] i_prescaler,
input [PERIOD_WIDTH - 1:0] i_period,
input [DUTY_CYCLE_WIDTH - 1 : 0] i_dutycycle,
output logic [DATA_WIDTH - 1 : 0] o_pwm_clk,
output logic [COUNTER_WIDTH - 1 : 0] o_clk_counter,
output logic [COUNTER_WIDTH - 1 : 0]
counter_pwm
);
//localparam COUNTER_WIDTH =
26;
localparam LEFT_ALIGNMENT =
2'b00;
localparam RIGHT_ALIGNMENT =
2'b01;
localparam CENTER_ALIGNMENT =
2'b10;
localparam UP_COUNTING =
1'b1;
localparam DOWN_COUNTING =
1'b0;
end
end
end
else begin
clk_counter <= clk_counter;
end
end
end
always_comb begin
if (!i_reset) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
else begin
if (i_CS) begin
if (i_countermode == DOWN_COUNTING) begin
if (i_alignment == LEFT_ALIGNMENT) begin
o_pwm_clk = (clk_counter > counter_pwm) ?
{(DATA_WIDTH-1)'('b0), 1'b1} : {(DATA_WIDTH-1)'('b0), 1'b0};
end
else if (i_alignment == RIGHT_ALIGNMENT) begin
o_pwm_clk = (clk_counter > counter_pwm) ?
{(DATA_WIDTH-1)'('b0), 1'b0} : {(DATA_WIDTH-1)'('b0), 1'b1};
end
else if (i_alignment == CENTER_ALIGNMENT) begin
if (clk_counter < left_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
else if (clk_counter >= left_edge && clk_counter <=
right_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b1};
end
else if (clk_counter > right_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
else begin
o_pwm_clk = o_pwm_clk; // This case seems
redundant
end
end
else begin
o_pwm_clk = o_pwm_clk; // Default case
end
end
else begin
if (i_alignment == LEFT_ALIGNMENT) begin
o_pwm_clk = (clk_counter <= counter_pwm) ?
{(DATA_WIDTH-1)'('b0), 1'b1} : {(DATA_WIDTH-1)'('b0), 1'b0};
end
else if (i_alignment == RIGHT_ALIGNMENT) begin
o_pwm_clk = (clk_counter <= counter_pwm) ?
{(DATA_WIDTH-1)'('b0), 1'b0} : {(DATA_WIDTH-1)'('b0), 1'b1};
end
else if (i_alignment == CENTER_ALIGNMENT) begin
if (clk_counter < left_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
else if (clk_counter >= left_edge && clk_counter <=
right_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b1};
end
else if (clk_counter > right_edge) begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
else begin
o_pwm_clk = o_pwm_clk; // This case seems
redundant
end
end
else begin
o_pwm_clk = o_pwm_clk; // Default case
end
end
end
else begin
o_pwm_clk = {(DATA_WIDTH-1)'('b0), 1'b0};
end
end
end
endmodule
Explain code:
Module Overview:
• Inputs:
o i_clk: System clock
o i_reset: Reset signal
o i_enable: Enables PWM functionality
o i_wenable: Enables writing to control registers
o i_address: Selects which control register to write to
o i_renable: Enables reading the PWM output
o i_data: Data to be written to control registers
• Outputs:
o o_pwm_pulse: The generated PWM signal
Key Components:
• Parameters: Define various constants such as data width, duty cycle width,
source clock value, etc.
• Signals: Declare internal signals used for control and data flow.
• Timer_Prescaler Instance: A module instance responsible for dividing the
clock frequency and generating the PWM waveform.
• Combinational Logic: Assigns values to signals based on inputs and
parameters.
• Sequential Logic: Implements state-based behavior using an always_ff
block, controlled by the clock and reset signals.
Code Structure:
• Parameter Declarations: Sets fixed values for various parameters.
• Signal Declarations: Declares internal signals.
• Assignment Statements: Assigns values to signals based on calculations and
parameter values.
• Always_ff Block: Implements the main state machine logic, handling clock
events and reset.
• Timer_Prescaler Instance: Instantiates the Timer_Prescaler module with
necessary connections.
Functionality:
• Initialization: Upon reset, signals are set to default values.
• Data Writing: When i_wenable is active, writes data to control registers for
frequency and duty cycle.
• PWM Generation: When i_enable is active, enables the prescaler and starts
PWM generation based on configured parameters.
• Output Reading: When i_renable is active, outputs the generated PWM
signal.
Key Points:
• The code uses a state machine to control the PWM generation process.
• The Timer_Prescaler module handles clock division and PWM waveform
creation.
• Control registers allow configuring frequency and duty cycle.
• The code supports different alignment modes (left, right, center) for the
PWM pulse.