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.

Why I can't get the correct counter?

Status
Not open for further replies.

staraimm

Full Member level 2
Joined
Oct 21, 2006
Messages
133
Helped
5
Reputation
10
Reaction score
1
Trophy points
1,298
Activity points
2,178
mixed single- and double-edge expressions

Hi,

I wrote the code as the following, and I compiled it using Quartus II.

module edgectrl(clk, clr, en, outnum);
input clk, clr, en;
output[7:0] outnum;
reg[7:0] outnum;

always @ (posedge clk or negedge clr)
begin
if(~clr)
begin
if(~en)
outnum <= 0;
else
outnum <= outnum + 8'h1;
end
else
outnum <= 0;
end
endmodule

But I can't get the corrct counter, the result is in the attachment. Can anybody tell me why?
 

verilog mixed single and double-edge expressions

Try this:

Code:
module edgectrl(clk, clr, en, outnum); 
input clk, clr, en; 
output[7:0] outnum; 
reg[7:0] outnum; 

always @ (posedge clk or negedge clr or en) 
begin 
	if(clr == 1'b0) 
		outnum = 0; 
	else 
		if(en == 1'b1) 
			outnum = outnum + 8'h1; 
	end 
endmodule
 

how to use async clear in synchronous fpga design

I think the expression " always @ (posedge clk or negedge clr or en) " is not allowed.
 

mixed single and double edge expressions are not

Why not?
It runs, and it does what you need.
 

error (10122):verilog hdl event

What compiler do you use? I use the Quartus II and it reports error:
Error (10122): Verilog HDL Event Control error at edgectrl.v(6): mixed single- and double-edge expressions are not supported.
 

topics counter always at 0

Ahh, ok.
Then remove "or en" i have put this to make simulation faster.
 

verilog bad design practices

Hi staraimm, your original 'clr' polarity and 'en' logic are somewhat confused. Try this:
Code:
module top (clk, clr, en, outnum);
  input             clk, clr, en;
  output reg  [7:0] outnum;

  always @ (posedge clk or posedge clr) begin
    if (clr)
      outnum <= 0;
    else
      outnum <= outnum + en;
  end
endmodule
smilermd, putting 'en' into your 'always' sensitivity list causes the counter to be clocked by 'en'. That caused the Quartus error, because it is unable to synthesize multiple clocks.
 
mixing of edge trigerred and level trigerred not allowed. not synthesisable
 

I want to realize the counter drived by the clk signal and cleared by the clr signal.

The waveform is something as follows.
 

Hi staraimm, your jpeg diagrams don't clearly show how you want the counter to behave. They don't show your desired output signals. When I looked at result.jpg, I assumed that 'clr' is an active high asynchronous reset, and 'en' is a synchronous count enable, but samplewave.jpg suggests something different.
 

The waveform in the samplewave.jpg expresses what I really want. On the positive edge of the clr signal, the counter is cleared to 0. And on the each positive edge of the clk signal, the counter must be added by 1.

The code as follows can't work, because all the events happen when the clr signal is high.

always @ (posedge clk or posedge clr)
begin
....
end

hi, Echo47, can you tell me how to realize it?
 

Can anybody help me to realize the counter?
 

if you want a asynchronous reset/synchronous enable counter

always ©(posedeg clk or posedge clr)
begin
if(clr)
counter <= 0;
else if(en)
counter <= counter + 1'b1;
end

if you want synchronous reset/synchronous enable counter

always ©(posedge clk)
begin
if(clr)
counter <= 0;
else if(en)
counter <= counter + 1'b1;
end
 

Hi staraimm,

You want to clear your counter on the positive edge of the clr and increment at the positive edge of the clock. Right?. After the positive edge of clr you are not resetting "clr" and it is always high. Inside your always block you are clearing the counter when the clr is high and it has the highest priority. So whenever your always block is invoked output of the counter will always be zero. You have to put your clr signal to low once the counter is reset. Your counter will work fine.

Cheers:)
 

If you really want a rising-edge-triggered clear (and not just an active-high clear or synchronous clear), then you may be in trouble because currently available FPGAs aren't designed to implement counters with multiple clocks. I suppose you could build an asynchronous one-shot that converts the rising edge of clr into a narrow asynchronous clear pulse, but that would be poor design practice. A better solution is to use an active-high clear, or better yet rethink your overall design to make everything synchronous to the clock.
 

Hi Echo,
as you said, "build an asynchronous one-shot that converts the rising edge of clr into a narrow asynchronous clear pulse, but that would be poor design practice."

Can you please explain me how to build asynchronous one-shot and why it is a poor design practice?

Thanks,
 

Hi, everyone. Glad to get all your response.

But the clr and en signals can't be controlled by my design and I just can use them.

In order to realize the counter, I use the code as follows.

wire tmpclk = clr & (~en);

always @ (posedge clk or posedge tmpclk)
begin
if(tmpclk)
count <= 0;
else
count <= count - 1;
end

But if so, I use the gated tmpclk and I am learned that it's not perfect to use the gated clk.
 

Hi staraimm, if this was my project, I would try to build a fully synchronous design, perhaps by using a higher-frequency clock. However I don't know enough about your project's input-output timing requirements to suggest a satisfactory solution. Try browsing the Altera papers that I've linked below - maybe they will help you create a good solution.

Hi xstal, there are several ways to build a one-shot (narrow pulse generator), but all these methods are asynchronous and rely upon the device's propagation delays, and are therefore not recommended for FPGA design.

Bad method #1: use an AND gate with a slow inverter. Output = Input AND Delayed_Inverted_Input. The Output will pulse high very briefly, depending on the inverter's propagation delay plus its net delay. (Remember, this is not recommended.)

Bad method #2: use a slow D-flop that resets itself. Connect the Input to the flop's clock. Tie its D input high. Connect Q to the flop's asynchronous reset. The Q output will pulse high very briefly, depending on the flop's propagation delay plus the reset net delay. (Remember, this is not recommended.)

We are discussing an Altera project, so for more explanation of good versus bad design practices, refer to this @ltera paper: "Design Guidelines for Optimal Results in FPGAs"
**broken link removed**
or this one from the qu(at)rtus handbook: "Design Recommendations for @ltera Devices"
https://www.altera.com/literature/hb/qts/qts_qii51006.pdf
 

    staraimm

    Points: 2
    Helpful Answer Positive Rating
Hi there,
I just started exploring the "wonderful":roll: world of HDLs, so I'm no expert.
Maybe that's a solution to your problem:
Code:
module edgectrl(clk, clr, en, outnum);
    input clk, clr, en;
    output [7:0] outnum;
	 reg [7:0] outnum;
	 reg clr_next, clr_next_clr, clr_next_clr_dly;

	always @(negedge clk)
		clr_next_clr = clr_next_clr_dly;

	always @(posedge clk)
	begin
		clr_next_clr_dly = clr_next;
		if(clr_next)
			outnum = 0;
		else
			if(en)
				outnum = outnum + 1;
	end
	
	always @(posedge clr or posedge clr_next_clr)
		if(clr_next_clr) clr_next = 0;
		else clr_next = 1;
		
endmodule

It just stores the edge of the clear signal, buffers it using a master-slave flip flop and uses its output for resetting your counter synchronously as well as clearing the stored clr-signal edge.
Had a hard time figuring out how to write this in behaviour modelling, but it was a nice Verilog semantic lesson to me.

HTH
dsp_
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top