- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
oops:
Sorry, it didn't keep my formating, also I left out a line: assign counter_o = counter_r; Pete- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page