Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20754 Discussions

Ok I must be an idiot :P

Altera_Forum
Honored Contributor II
1,312 Views

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
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
375 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

oops: 

 

Sorry, it didn't keep my formating, 

 

also I left out a line: 

 

assign counter_o = counter_r; 

 

Pete
0 Kudos
Altera_Forum
Honored Contributor II
375 Views

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
0 Kudos
Reply