Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17241 Discussions

This short verilog code is not working

Altera_Forum
Honored Contributor II
4,382 Views

The following code is supposed to be easy and straight forward, but its not giving the correct results! 

 

I want the output to follow input whenever the counter = 5. But whenever there is an edge in the input, i want the counter to load the value of 3. The counter is initialied to 3. 

 

assign invdata = ~data; 

always @ (posedge clk or posedge data or posedge invdata) begin 

if (clk) begin  

if (counter==5) begin output<=input; counter<=1; end 

else counter<=counter+1; 

end 

 

else if (data) counter<=3; 

else counter<=3; 

end 

 

the results shows that the counter will always be stuck on 3. but, on every clock edge the counter will change randomly to around 5 values then go back to 3 after a while.why? 

isnt that code 100% correct? if not, whats the correct code to do the same job? 

im simulating on quartus II. 

 

Another thought, what if data has a positive edge, and the it enters the above always loop at the same time clk is high. this way it will act exactly the same as if a posedge clk occured. no? and thats wrong! what should i do in such a case? 

 

PS: the input is a clock with period = 200ns. 

clk is a clk with period = 20ns. 

 

Thanx.
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
3,380 Views

A few things to mention: 

1 - It looks like you're getting confused in your signal names. You're using a signal called data but you're also using a signal called input. Are they supposed to be the same thing? 

 

2 - You should never use the names "input" or "output" to name signals. Those are keywords in Verilog and should only be used when declaring inputs and outputs to a module, task, or function. 

 

3 - You're event triggerred always block. You need to keep in mind that what you are writing is going to be turned into hardware. Flip-flops in hardware have a single clock input. You cannot use a rising and falling edge of a signal as a clock input to a flip-flop. Your code is actually not synthesizable. You have a clock input, data input, and a asynchronous set and/or reset signal at your disposal. 

 

4 - It's good practice to provide a reset signal to initialize your registers to a pre-determined state. 

 

 

Does this meet your needs? I haven't compiled it so there might be a syntax error or two: 

module ocd( input clk, // clock input reset_n, // active low reset input data_in, output data_out ); reg last_data; reg counter; wire edge; assign edge = last_data ^ data_in; always @(posedge clk or negedge reset_n) begin if(!reset_n) begin data_out <= 1'b0; last_data <= 1'b0; counter <= 3'd0; end else begin last_data <= data_in; counter <= counter + 3'd1; if(edge) counter <= 3'd3; else if(counter == 5) begin counter <= 3'd1; data_out <= data_in; end end end endmodule
0 Kudos
Altera_Forum
Honored Contributor II
3,380 Views

The original code is edge sensitive only for posedge(invdata) and level sensitive for clk and data. The code isn't generally unsynthesizable but most likely neither intended this way nor creating any meaningful logic behaviour. Additionally latching on data == 1 and sampling on posedge(invdata) respectively negedge(data) creates a timing violation for the edge triggered flip-flop.

0 Kudos
Altera_Forum
Honored Contributor II
3,380 Views

 

--- Quote Start ---  

A few things to mention: 

1 - It looks like you're getting confused in your signal names. You're using a signal called data but you're also using a signal called input. Are they supposed to be the same thing? 

 

2 - You should never use the names "input" or "output" to name signals. Those are keywords in Verilog and should only be used when declaring inputs and outputs to a module, task, or function. 

 

3 - You're event triggerred always block. You need to keep in mind that what you are writing is going to be turned into hardware. Flip-flops in hardware have a single clock input. You cannot use a rising and falling edge of a signal as a clock input to a flip-flop. Your code is actually not synthesizable. You have a clock input, data input, and a asynchronous set and/or reset signal at your disposal. 

 

4 - It's good practice to provide a reset signal to initialize your registers to a pre-determined state. 

 

 

Does this meet your needs? I haven't compiled it so there might be a syntax error or two: 

module ocd( input clk, // clock input reset_n, // active low reset input data_in, output data_out ); reg last_data; reg counter; wire edge; assign edge = last_data ^ data_in; always @(posedge clk or negedge reset_n) begin if(!reset_n) begin data_out <= 1'b0; last_data <= 1'b0; counter <= 3'd0; end else begin last_data <= data_in; counter <= counter + 3'd1; if(edge) counter <= 3'd3; else if(counter == 5) begin counter <= 3'd1; data_out <= data_in; end end end endmodule  

--- Quote End ---  

 

 

Sorry for the typo. Yes input means the data, as the keywords wont even compile successfully. 

 

According to ur code, edge is high only for a short amount of time. so if edge is high only between two clock pulses and goes back to low before the next clock pulse, the edge wont be detected in such case. right?
0 Kudos
Altera_Forum
Honored Contributor II
3,380 Views

 

--- Quote Start ---  

The original code is edge sensitive only for posedge(invdata) and level sensitive for clk and data. The code isn't generally unsynthesizable but most likely neither intended this way nor creating any meaningful logic behaviour. Additionally latching on data == 1 and sampling on posedge(invdata) respectively negedge(data) creates a timing violation for the edge triggered flip-flop. 

--- Quote End ---  

 

 

I want the flip flop to be triggered on both posedge and negedge of my data input signal. 

I imagined the clk port of the FF is connected to an output of an OR gate, and triggered on posedge. This OR gate has (clk, data, invdata) as its inputs. whats wrong with such setup?
0 Kudos
Altera_Forum
Honored Contributor II
3,380 Views

It's not possible to trigger a single FF on both edges, neither a discrete device, e. g. a 74HC74 nor a FPGA FF. It doesn't work directly or by any trick (as defining an inverted signal). 

 

To design logic, that is sensitive for both edges, you can use two FFs and combine the results, but you have to be careful not to generate glitches in the output. 

 

Another option is synchronous edge detection by a sufficient fast clock.
0 Kudos
Altera_Forum
Honored Contributor II
3,380 Views

 

--- Quote Start ---  

I want the flip flop to be triggered on both posedge and negedge of my data input signal. 

I imagined the clk port of the FF is connected to an output of an OR gate, and triggered on posedge. This OR gate has (clk, data, invdata) as its inputs. whats wrong with such setup? 

--- Quote End ---  

 

 

 

I modified the code you got from jacobjones, because "edge" is a reserved keyword in Verilog. The code could not compiled by Quartus. 

 

I inserted two edge detectors, which looks for the rising and the falling edge of your input signal. I check at least the basic function. 

 

module ocd( 

input clk, // clock 

input reset_n, // active low reset 

 

input data_in, 

output reg data_out 

); 

 

reg last_data; 

reg [2:0] counter; 

wire edge_pos /* synthesis keep */; 

wire edge_neg /* synthesis keep */; 

// wire edge; 

// assign edge = last_data ^ data_in; 

 

assign edge_pos = !last_data & data_in; // detects posedge in data_in 

assign edge_neg = last_data & !data_in; // detects negedge in data_in 

always @(posedge clk or negedge reset_n) begin 

if(!reset_n) begin 

data_out <= 1'b0; 

last_data <= 1'b0; 

counter <= 3'd0; 

end else begin 

last_data <= data_in; 

counter <= counter + 3'd1; 

 

if(edge_pos ^ edge_neg ) counter <= 3'd3; 

// if(edge) counter <= 3'd3; 

else if(counter == 5) begin 

counter <= 3'd1; 

data_out <= data_in; 

end 

end 

end 

 

endmodule
0 Kudos
Reply