module CS_Detect (
Counter,
CS,
E,
CLK,
EDGES
);
output [3:0] Counter; // Used to time the edges
output CS; // The main output
output E; // A debugging output
// gives a pulse on rising edge of EDGES
input CLK;
input EDGES;
reg T;
reg E;
reg CS;
reg Counter;
always @(EDGES or T)
begin
E <= EDGES & !T;
end
always @(posedge CLK)
begin
if (EDGES & !T) begin // CS Rising
if (Counter > 0) begin // OMFG, the counter HASN'T timed out. This is the second rising edge!
CS = 0;
end else begin // Counter has timed out. This is a possible first edge
Counter = 15;
end
end
if (!EDGES & T) begin // CS Falling
CS = 1;
end
if (Counter > 0) Counter = Counter - 1;
end
always @(negedge CLK)
begin
T = EDGES;
end
endmodule
module CS_Detect
(
input clk, edges,
output reg cs
);
reg [1:0] edges_reg;
reg [1:0] pos_edges;
reg [3:0] cnt;
always @(posedge clk)
edges_reg <= {edges[0],edges}; // just store input, shift-in reg
always @(posedge clk)
if ( edges_reg == 2'b01 ) // if rising edge
pos_edges <= {pos_edges[0], 1'b1}; // shift in '1'
always @(posedge clk)
if ( pos_edges[0] ) // if first pos. edge detected
cnt <= cnt + 1'b1; // incr. the counter
else
cnt <= 4'h0;
always @(posedge clk)
if ( edges_reg == 2'b10 ) // falling edge
cs <= 1'b1;
else if ( edges_reg == 2'b11 & !(&cnt) ) // 2 rising edges AND
// cnt < 15 (not all cnt bits are HIGH)
cs <= 1'b0;
endmodule
That's right. It's only on a rising edge that I'm interested in the time. On a falling edge, CS should always go high.1. it times out only when EDGE rises.
As a beginner, I'm still not sure how to initialise the values.2. CS value is unknown till EDGE either rises or falls ? The counter has no initial value either.
That's another thing I don't fully understand. I get the general idea, but I'm not exactly sure which I should use, and when.3. Try to use blocking and non blocking statements properly.
4. your spec, "within 15 clocks" is not very clear. Within 15 clocks from when ?
look at my version, I hope it gives an idea how to do the job;
did not test my version on a simulator, may be something needs to be fixed.
always @(posedge clk)
edges_reg <= {edges[0],edges}; // just store input, shift-in reg
always @(posedge clk)
edges_reg <= {edges_reg[0],edges}; // just store input, shift-in reg
You don't get a synthesis error, the code has no problem in this regardthere are to assignments that can happen at the same time:
if (Counter > 0) Counter = Counter - 1;
and
if (EDGES & !T) /.../
Counter = 15;
you will get a synthesis error or the tool will decide how to implement it;
You don't get a synthesis error, the code has no problem in this regard.
- The original edge detection is incorrect in so far, that it's only sensitive to transitions between the negative and the positive edge, which seems not to correspond to the specification.
- The edge detection scheme suggested by j_andr (despite of the mentioned syntax error) is basically on the right track.
You don't need to repeat this mantra-like statement. I think, I basically understood the intention of your specification, although the specification isn't very clear, as others already mentioned.Please see the image attached to my original post.
I see, that my comment wasn't clear enough. But you also didn't take the effort to think about it, although you already experienced problems with your code.No. There is code there to detect both types of edge. See the "// CS Falling" and "// CS Rising" comments
Yes, I mentioned that the code has errors. The basic edge detection scheme is correct, not the way how it's acting on first or second one. You'll find the basic concept, shifting the input signal into a chain of two, better three registers on one clock edge, in many applications.To me is seems wrong because it only seems to be sensitive to the first two rising edges ever, not to all rising edges.
you are right, I was wrong, quartus compiled it smoothly;FvM said:You don't get a synthesis error, the code has no problem in this regard
module CS_Detect
(
input clk, edges,
output reg cs
);
reg edges_reg = 1'b1;
always @(posedge clk)
edges_reg <= edges;
wire pos_pulse = edges & !edges_reg;
reg [14:0] train;
always @(posedge clk)
train <= {train[13:0], pos_pulse};
always @(posedge clk)
if ( !edges ) cs <= 1'b1;
else if ( train != 15'h0 && pos_pulse ) cs <= 1'b0;
endmodule
Code:always @(posedge clk) train <= {train[13:0], pos_pulse}; always @(posedge clk) if ( !edges ) cs <= 1'b1; else if ( train != 15'h0 && pos_pulse ) cs <= 1'b0;
always @(posedge clk)
if ( !edges ) cs <= 1'b1;
else if ( !train[14] && train && pos_pulse ) cs <= 1'b0;
always @(posedge clk)
train <= {train[13:0], pos_pulse};
Sounds like you misunderstood the code. Both cases can't happen because a "one" in the train SR is marking a rising edge of the EDGE input rather than a high state. You'll have exactly a single "one" in the train register, when the logic triggers.The problem I see with this approach is that a valid train looks like:
* 0001111110000000
and an invalid train looks like:
* 1111111110000000
Sounds like you misunderstood the code. Both cases can't happen because a "one" in the train SR is marking a rising edge of the EDGE input rather than a high state. You'll have exactly a single "one" in the train register, when the logic triggers.
P.S.: Exact fall back condition and possible retriggering hasn't been specified yet.
Yes, as already mentioned. And although you possibly think, it doesn't clearly specify all cases. The latest text however does, as far as I see.P.S. Did you look at the attached image?
- The waveform neither shows the clock nor defines what's exactly considered a clock cycle. Your initial code demonstrates, why this matters.
- It suggests a fall-back condition, but doesn't claraify, if it's e.g. valid also during the 15 clocks window
So all implementations have been partly based on guesses.
/.../
So to be valid:
* train must be non-zero
* train[14] must be zero
* train[0] must be set after train is tested for validity.
Perhaps it should be:
/.../
but have a better version, it at least compiles without errors;
module CS_Detect (
CS,
CLK,
EDGES
);
output CS;
input CLK;
input EDGES;
reg edges_reg;
reg [3:0] Counter;
reg CS;
wire pos_pulse = EDGES & !edges_reg;
wire neg_pulse = !EDGES & edges_reg;
always @(posedge CLK)
begin
edges_reg <= EDGES;
if (pos_pulse == 1) begin
Counter <= 15;
end else begin
if (Counter > 0) Counter <= Counter - 1;
end
end
always @(posedge CLK)
begin
if ((pos_pulse == 1) && (Counter > 0)) begin
CS <= 0;
end else begin
if (neg_pulse == 1) begin
CS <= 1;
end
end
end
endmodule
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?