Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
18 years ago

Ok I must be an idiot :P

Hi people,

I am new to this so go easy on me. What I am trying to make is a block that has 3 inputs up, down, reset and one 12bit output. when i pulse up i want it to count up by 3, when I pulse down i want it to count down by 3, when i pulse reset I want it to reset to 250.

here is my code atm:

module updown (
up , 
down , 
reset ,
counter_out 
); // End of port list
//-------------Input Ports-----------------------------
input up ;
input down ;
input reset ;
//-------------Output Ports----------------------------
output  counter_out ;
//-------------Input ports Data Type-------------------
wire up ;
wire down ;
wire reset ;
//-------------Output Ports Data Type------------------
reg  counter_out ;
//-------------Internal Variables----------------------
//------------Code Starts Here-------------------------
always @ (posedge reset or posedge up or posedge down )
	begin
		if (reset) begin
			counter_out =# 3 250 ;
		end 
		else if (down) begin
			counter_out =# 3 counter_out - 3 ;
		end 
		else if (up) begin
			counter_out =# 3 counter_out + 3 ;
		end
	end
endmodule

Atm reset and up work if i hit down it counts down for the entire time that down is held high. If i change up and down location in the if statement then down works and up does not....

Chris

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    on the one hand, I see a lack of clarity with the Verilog always @ construct that requirers to use a posedge or negedge for an asynchronous reset. It's much clearer in VHDL to my opinion. But the basic point is that you can't have a synchronous register or a group of registers (e. g. a counter) with more than one clock input. If your design actually has two separate clocks, you must first preprocess these signals to get a single unequivocal clock and e. g. separate up and down qualifiers.

    Regards,

    Frank
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Chris:

    The problem is in the sensitivity list applied. You really want it evaluated on both rising and falling edges, and tell it to hold in the non-case.

    However, that being said. it is much better to do a synchronous design as follows:

    module updown (

    input clk_i,

    input reset_i,

    input up_i,

    input down_i,

    output [11:0] counter_o

    );

    reg [2:0] up_s;

    reg [2:0] down_s;

    reg [11:0] counter_r;

    wire up_rise_edge_p <= up_s[1] & ~up_s[2];

    wire down_rise_edge_p <= down_s[1] & ~down_s[2];

    always @(posedge clk_i)

    begin

    if (reset_i)

    begin

    counter_r <= 12'd250;

    up_s <= 3'b111;

    down_s <= 3'b111;

    end

    else

    begin

    up_s <= {up_s[1:0],up_i};

    down_s <= {down_s[1:0],down_i};

    if (up_rise_edge_p)

    begin

    if (down_rise_edge_p)

    counter_r <= counter_r;

    else

    counter_r <= counter_r + 12'd3;

    end

    else

    begin

    if (down_rise_edge_p)

    counter_r <= counter_r - 12'd3;

    else

    counter_r <= counter_r;

    end

    end

    end

    endmodule

    This takes care of async up and down signals, but glitch eaters could also be added if necessary. This also takes care of a non-count case of both up and down being pressed at the same time.

    Pete
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    oops:

    Sorry, it didn't keep my formating,

    also I left out a line:

    assign counter_o = counter_r;

    Pete
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello Pete,

    a full synchronous design as you presented would actually be the best solution. It could be however, that either no appropriate clock is present or that the up/down events are too fast for synchronous edge detection in relation to an existing clock. Special solutions are thinkable. But we don't know the timing constraints and thus it's meaningful to point out FPGA design standards.

    To clarify the always @ aspect of the original code example: Only one event expression from the sensitivity list can actually be an edge sensitive trigger, either positive or negative. It's the signal not appearing in a following if statement. All other events are asynchronous preloads.

    If you want to trigger sequential functions directly from two separate clocks, you need two separate always blocks. But than the issue is to combine the outputs from both blocks. You could e. g. have two separate counters and simply add the count values. But the sum would be undefined during events until a steady state is reached.

    Regards,

    Frank