📄 pwmavalonexample.v
字号:
/***************************************************************************/
/* File: pwm_avalon_interface.v */
/* Description: Top level module. Instantiates pwm_task_logic and */
/* pwm_register_file modules and adds Avalon slave interface. */
/***************************************************************************/
module pwm_avalon_interface
( clk,
resetn,
avalon_chip_select,
address,
write,
write_data,
read,
read_data,
pwm_out
);
//Parameter values to pass to pwm_register_file instance
parameter clock_divide_reg_init = 32'h0000_0000;
parameter duty_cycle_reg_init = 32'h0000_0000;
//Avalon_Slave_PWM Avalon I/O
input clk; //System clock - tied to all blocks
input resetn; //System reset - tied to all blocks
input avalon_chip_select; //Avalon Chip select
input [1:0]address; //Avalon Address bus
input write; //Avalon Write signal
input [31:0]write_data; //Avalon Write data bus
input read; //Avalon Read signal
output [31:0]read_data; //Avalon Read data bus
//Avalon_Slave_PWM Exported I/O
output pwm_out; //PWM output signal
//Avalon_Slave_PWM Interal Nodes
wire [31:0] pwm_clock_divide; //Clock divide wire from register file to pwm task logic
wire [31:0] pwm_duty_cycle; //Duty cycle value from register file to pwm task logic
wire pwm_enable; //PWM enable signal from register file to pwm task logic
//PWM Instance
pwm_task_logic task_logic
(
.clk (clk ),
.pwm_enable (pwm_enable),
.resetn (resetn),
.clock_divide (pwm_clock_divide),
.duty_cycle (pwm_duty_cycle),
.pwm_out (pwm_out)
);
//Register File instance
pwm_register_file #(clock_divide_reg_init, duty_cycle_reg_init) memory_element
(
.clk (clk),
.resetn (resetn),
.chip_select (avalon_chip_select),
.address (address),
.write (write),
.write_data (write_data),
.read (read),
.read_data (read_data),
.pwm_clock_divide (pwm_clock_divide),
.pwm_duty_cycle (pwm_duty_cycle),
.pwm_enable (pwm_enable)
);
endmodule
寄存器描述文件:
module pwm_register_file
( //Avalon Signals
clk,
resetn,
chip_select,
address,
write,
write_data,
read,
read_data,
//PWM Output Signals
pwm_clock_divide,
pwm_duty_cycle,
pwm_enable
);
//Parameters
parameter clock_divide_reg_init = 32'h0000_0000;
parameter duty_cycle_reg_init = 32'h0000_0000;
//Inputs
input clk; //System Clock
input resetn; //System Reset
input chip_select; //Avalon Chip select signal
input [1:0] address; //Avalon Address bus
input write; //Avalon Write signal
input [31:0] write_data; //Avalon Write data bus
input read; //Avalon read signal
//Outputs
output [31:0] read_data; //Avalon read data bus
output [31:0] pwm_clock_divide; //PWM clock divide drive signals
output [31:0] pwm_duty_cycle; //PWM duty cycle drive signals
output pwm_enable; //PWM enable drive signals
//Signal Declarations
reg [31:0] clock_divide_register; //Clock divider register
reg [31:0] duty_cycle_register; //Duty Cycle Register
reg enable_register; //Enable Bit
reg [31:0] read_data; //Read_data bus
//Nodes used for address decoding
wire clock_divide_reg_selected, duty_cycle_reg_selected, enable_reg_selected;
//Nodes for determining if a valid write occurred to a specific address
wire write_to_clock_divide, write_to_duty_cycle, write_to_enable;
//Nodes for determining if a valid read occurred to a specific address
wire read_to_clock_divide, read_to_duty_cycle, read_to_enable;
//Nodes used to determine if a valid access has occurred
wire valid_write, valid_read;
//Start Main Code
//address decode
assign clock_divide_reg_selected = !address[1] & !address[0]; //address 00
assign duty_cycle_reg_selected = !address[1] & address[0]; //address 01
assign enable_reg_selected = address[1] & !address[0]; //address 10
//determine if a vaild transaction was initiated
assign valid_write = chip_select & write;
assign valid_read = chip_select & read;
//determine if a write occurred to a specific address
assign write_to_clock_divide = valid_write & clock_divide_reg_selected;
assign write_to_duty_cycle = valid_write & duty_cycle_reg_selected;
assign write_to_enable = valid_write & enable_reg_selected;
//determine if a read occurred to a specific address
assign read_to_clock_divide = valid_read & clock_divide_reg_selected;
assign read_to_duty_cycle = valid_read & duty_cycle_reg_selected;
assign read_to_enable = valid_read & enable_reg_selected;
//Write to clock_divide Register
always@(posedge clk or negedge resetn)
begin
if(~resetn)begin //Async Reset
clock_divide_register <= clock_divide_reg_init; //32'h0000_0000;
end
else begin
if(write_to_clock_divide) begin
clock_divide_register <= write_data;
end
else begin
clock_divide_register <= clock_divide_register;
end
end
end
//Write to duty_cycle Register
always@(posedge clk or negedge resetn)
begin
if(~resetn)begin //Async Reset
duty_cycle_register <= duty_cycle_reg_init; //32'h0000_0000;
end
else begin
if(write_to_duty_cycle) begin
duty_cycle_register <= write_data;
end
else begin
duty_cycle_register <= duty_cycle_register;
end
end
end
//Write to enable register
always@(posedge clk or negedge resetn)
begin
if(~resetn)begin //Async Reset
enable_register <= 1'b0;
end
else begin
if(write_to_enable)begin
enable_register <= write_data[0];
end
else begin
enable_register <= enable_register;
end
end
end
//Read Data Bus Mux
always@(read_to_clock_divide or read_to_duty_cycle or read_to_enable or clock_divide_register or duty_cycle_register or enable_register)
begin
if(read_to_clock_divide) begin
read_data = clock_divide_register;
end
else if(read_to_duty_cycle) begin
read_data = duty_cycle_register;
end
else if(read_to_enable) begin
read_data = {31'd0,enable_register};
end
else begin
read_data = 32'h0000_0000;
end
end
//assign register values to register file outputs to the PWM
assign pwm_clock_divide = clock_divide_register;
assign pwm_duty_cycle = duty_cycle_register;
assign pwm_enable = enable_register;
endmodule
PWM生成逻辑描述文件:
/***************************************************************************/
/* File: pwm_task_logic.v */
/* Description: This module contains the core of the pwm functionality. */
/* The clock_divide and duty_cycle inputs are used in conjunction with */
/* a counter to determine how long the pwm output stays high and low. */
/* The output is 1 bit. */
/***************************************************************************/
module pwm_task_logic
(
clk,
pwm_enable,
resetn,
clock_divide,
duty_cycle,
pwm_out
);
//Inputs
input clk; //Input Clock to be divided
input [31:0] clock_divide; //Clock Divide value
input [31:0] duty_cycle; //Duty Cycle vale
input pwm_enable; //Enable signal
input resetn; //Reset
//Outputs
output pwm_out; //PWM output
//Signal Declarations
reg [31:0] counter; //PWM Internal Counter
reg pwm_out; //PWM output
//Start Main Code
always @(posedge clk or negedge resetn) //PWM Counter Process
begin
if (~resetn)begin
counter <= 0;
end
else if(pwm_enable)begin
if (counter >= clock_divide)begin
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
else begin
counter <= counter;
end
end
always @(posedge clk or negedge resetn) //PWM Comparitor
begin
if (~resetn)begin
pwm_out <= 0;
end
else if(pwm_enable)begin
if (counter >= duty_cycle)begin
pwm_out <= 1'b1;
end
else begin
if (counter == 0)
pwm_out <= 0;
else
pwm_out <= pwm_out;
end
end
else begin
pwm_out <= 1'b0;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -