89 lines
1.5 KiB
Verilog
89 lines
1.5 KiB
Verilog
module avalon_pwm
|
|
(
|
|
clk, wr_data, cs, wr_n, addr, clr_n, rd_data, pwm_out
|
|
);
|
|
|
|
input clk;
|
|
input [31:0] wr_data;
|
|
input cs;
|
|
input wr_n;
|
|
input addr;
|
|
input clr_n;
|
|
output [31:0] rd_data;
|
|
output [7:0] pwm_out;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Registers and wires
|
|
|
|
reg [31:0] div;
|
|
reg [31:0] duty;
|
|
reg [31:0] counter;
|
|
reg off;
|
|
reg [31:0] rd_data;
|
|
wire div_en, duty_en;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Avalon slave interface
|
|
|
|
//chip select and address decoder
|
|
assign div_en = cs & !wr_n & !addr ;
|
|
assign duty_en = cs & !wr_n & addr ;
|
|
|
|
//register write
|
|
always @(posedge clk or negedge clr_n)
|
|
begin
|
|
if (clr_n == 0)
|
|
begin
|
|
div <= 0;
|
|
duty <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (div_en) div <= wr_data;
|
|
if (duty_en) duty <= wr_data;
|
|
end
|
|
end
|
|
|
|
//register read
|
|
always @(*)
|
|
begin
|
|
if (addr == 0)
|
|
rd_data = div;
|
|
else
|
|
rd_data = duty;
|
|
end
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// PWM logic
|
|
|
|
//PWM counter
|
|
always @(posedge clk or negedge clr_n)
|
|
begin
|
|
if (clr_n == 0)
|
|
counter <= 0;
|
|
else
|
|
if (counter >= div)
|
|
counter <= 0;
|
|
else
|
|
counter <= counter + 1;
|
|
end
|
|
|
|
//PWM compare
|
|
always @(posedge clk or negedge clr_n)
|
|
begin
|
|
if (clr_n == 0)
|
|
off <= 0;
|
|
else
|
|
if (counter >= duty)
|
|
off <= 1;
|
|
else
|
|
if (counter == 0)
|
|
off <= 0;
|
|
else
|
|
off <= off;
|
|
end
|
|
|
|
assign pwm_out = {8{!off}};
|
|
|
|
endmodule
|