Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Implementation of PWM on FPGA

Status
Not open for further replies.

loki3118

Junior Member level 2
Junior Member level 2
Joined
Jun 26, 2013
Messages
23
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
238
Hello,

I recently switched from VHDL to Verilog to more utilize my background in programming in C++. I was given a project in which i need to implement PWM on a FPGA. I've been trying my best to do my research and look at examples of PWM that are floating around the internet. I written some code that I believe does what I would like, however Xilinx ISE compiler shot down my hopes.

If anyone could provide some feedback regarding the code that I have written it would be much appreciated. There are lots of errors with my code but at this moment I am reading up on the proper syntax of the Verilog.

Project specifications:
Xilinx FPGA Spartan-6
ISE Webpack
Switching Frequency of 5MHz (next iteration would duplicate this code to allow for 4 phases at 5MHz each)

Code:
module pwm(
    input clk,
    input write_data[31:0],
    input cs,
    input write_n,
    input addr,
    input clr_n,
    output read_data[31:0],
    output pwm_out
    );

reg	period;
reg	counter;
wire [31:0]	pulse_width;
wire [31:0]	off;
wire [31:0] period_en;
wire [31:0] pulse_width_en;

// Define period and pulse_width registers

always @(posedge clk or negedge clr_n)
begin

	if (clr_n == 0)
		begin

			period <= 32'h // Requires a period of 0.03 nanosecond
			pulse_width <= 32'h00000000;
		end
	else
		begin
 			if (period_en)
				period <=> // Same period issue
			else
				period <= period;=""> // Same period issue
			if (pulse_width_en)
				pulse_width <= write_data[31:0];
			else
				pulse_width <= pulse_width;
		end
 	 end

// Read access for period and pulse_width registers

	if (addr == 0)
		read_data = period;
	else
		read_data = pulse_width;

//Counter

always @(posedge clk or negedge clr_n)
begin
	if (clr_n == 0)
		counter <= 0;
	else
	if (counter >= period - 1)    // count from 0 to (period-1)
 		counter <= 0;
	else
		counter <= counter="" +="" 1;// Is this proper syntax?
	end

// Changes output while counter is less than pulse_width

always @(posedge clk or negedge clr_n)
begin
	if (clr_n == 0)
		off <= 0;
	else
	if (counter >= pulse_width)
		off <= 1;
	else
	if (counter == 0)
		off <= 0;
	else
		off <= off;
end

//Enables writing to period and pulse_width registers

assign period_en = cs & !write_n & !addr;

assign pulse_width_en = cs & !write_n & addr; 

// Output

assign pwm_out = !off;

endmodule
 

Things like: input write_data[31:0],

change to: input [31:0] write_data[31:0],

Wut? period <=> // Same period issue


Also, better not mix <= and = assignments in the same always block. Pick one and stick with it. I'd say the natural choice up there would be <=.

See: https://www.asic-world.com/tidbits/blocking.html
 

I followed your advice however there are problem with trying to index into arrays. I also made some other modifications to clean up the code.

Code:
module pwm (
input	clk,
input [31:0] write_data[31:0],
input	cs,
input	wrote_n,
input	addr,
input clr_n,
output pwm_out
);

// signal declarations
reg	period;
reg	counter;
reg	read_data;
reg	enables;
wire [31:0]	off[31:0];
wire [31:0]	period_en[31:0];
wire [31:0]	pulse_width_en[31:0];
wire [31:0]	pulse_width[31:0];



// Define contents of period and pulse_width registers including write access for these registers

always @(posedge clk or negedge clr_n)
begin
if (clr_n == 0)
begin
period <= 32'h00000000;
pulse_width[31:0] <= 32'h00000000;
end
else
begin
if (period_en[31:0])
period <= 00000001;	
else
period[31:0] <= period[31:0];
if (pulse_width_en[31:0])
pulse_width[31:0] <= write_data[31:0];
else
pulse_width[31:0] <= pulse_width[31:0];
end
end

// read access for period and pulse_width registers always @(addr or period or pulse_width)

if (addr == 0)
read_data <= period[31:0];
else
if
read_data <= pulse_width[31:0]; 

// counter which continually counts up to period
always @(posedge clk or negedge clr_n)
begin
if (clr_n == 0)
counter <= 0;
else
if (counter >= period - 1)// count from 0 to (period-1)
counter <= 0;
else
counter <= counter + 1;
end
// Turns output on while counter is less than pulse_width; otherwise turns output off. !off is connected to PWM output 

always @(posedge clk or negedge clr_n)
begin
if (clr_n == 0)
off[31:0] <= 0;
else
if (counter >= pulse_width[31:0])
off[31:0] <= 1;
else
if (counter == 0)
off[31:0] <= 0;
else
off[31:0] <= off[31:0];
end

// write enable signals for writing to period and pulse_width registers

assign period_en[31:0] = cs & !write_n & !addr;
assign pulse_width_en[31:0] = cs & !write_n & addr; 

// PWM output

assign pwm_out = !off[31:0];

endmodule
 

Oh man, crap. My bad. I accidentally forgot to erase some part.

Where you had:
Code:
input write_data[31:0],

You should write:
Code:
input [31:0] write_data,

And not like I accidentally wrote with [31:0] occuring two times on that line. What I wrote in the previous post would mean a 32-sized array of 32-bit words. Which was not my intent. My intent was just a single 32-bit word.

Also note that in verilog-2001 you cannot use arrays in the port declaration.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top