Guest
Hi,
I've ran into this design problem, which I would like to share my
thoughts about with you.
Hopefully, someone would inform me about the "best" or "better" way to
achieve the what I intend to do.
I wrote an FSM that handles memory reads/write from/to a synchronous
RAM module.
To simplify the problem, Let's assume the RAM accepts the following
inputs:
data - a data bus
address - an address bus
read_enable - a read signal
clk - a clock signal
the ram is basically designed like this:
always @(posedge clk)
begin: SYNCHRONOUS_RAM_READ
if (read_enable)
data <= ram[address];
else
data <= 0;
end
the read_enable signal, is generated by my FSM in certain situations.
This is a synchronous positive-edge triggered moore FSM and the signal
is asserted once i enter a certain state, and dis-asserted once i move
to the next state.
I want to achieve a Single Clock-Cycle read however the read_enable
signal is always meta-stable with respect to the ram:
the rising edge of the read-enable signal happens at the same time the
clk signal rises:
My FSM raises the signal (and passes the data) on enterance to the
read state -> positive clk edge
The RAM samples the signal on the positive edge of the clk.
So there's always a race between them: A "setup violation" on the
first clock edge, when the signals are asserted, and a "hold
violation" when the signals are dis-asserted.
(no real violations, of course, i'm just illustrating the races)
I figured out 2 possible solutions:
1. make the read state a multi-cycle state: this is the simplest
solution. just wait another clock cycle inside the state and the data
will be ready: but this won't achieve my goal of a single clock cycle
read.
2. make the RAM sensitive to the negative edge:
always @(negedge clk)
begin: SYNCHRONOUS_RAM_READ
if (read_enable)
data <= ram[address];
else
data <= 0;
end
this will absolutely solve the problem, as both the data and the read
signal will give the ram enough slack to sample them correctly.
(I could also make the FSM transition on negedge, and leave the RAM
posedge sensitive).
My question is though:
Is option 2 a generally recommended way to solve this problem?
Are there better solutions? how is this done correctly?
(I'm dissatisfied with my solution, since generally, i'll be getting
only half the clock period to stabilize my signals... so it might
become a problem if I would ever need to insert additional logic in
between the data paths.)
Thanks for your comments,
Itay
I've ran into this design problem, which I would like to share my
thoughts about with you.
Hopefully, someone would inform me about the "best" or "better" way to
achieve the what I intend to do.
I wrote an FSM that handles memory reads/write from/to a synchronous
RAM module.
To simplify the problem, Let's assume the RAM accepts the following
inputs:
data - a data bus
address - an address bus
read_enable - a read signal
clk - a clock signal
the ram is basically designed like this:
always @(posedge clk)
begin: SYNCHRONOUS_RAM_READ
if (read_enable)
data <= ram[address];
else
data <= 0;
end
the read_enable signal, is generated by my FSM in certain situations.
This is a synchronous positive-edge triggered moore FSM and the signal
is asserted once i enter a certain state, and dis-asserted once i move
to the next state.
I want to achieve a Single Clock-Cycle read however the read_enable
signal is always meta-stable with respect to the ram:
the rising edge of the read-enable signal happens at the same time the
clk signal rises:
My FSM raises the signal (and passes the data) on enterance to the
read state -> positive clk edge
The RAM samples the signal on the positive edge of the clk.
So there's always a race between them: A "setup violation" on the
first clock edge, when the signals are asserted, and a "hold
violation" when the signals are dis-asserted.
(no real violations, of course, i'm just illustrating the races)
I figured out 2 possible solutions:
1. make the read state a multi-cycle state: this is the simplest
solution. just wait another clock cycle inside the state and the data
will be ready: but this won't achieve my goal of a single clock cycle
read.
2. make the RAM sensitive to the negative edge:
always @(negedge clk)
begin: SYNCHRONOUS_RAM_READ
if (read_enable)
data <= ram[address];
else
data <= 0;
end
this will absolutely solve the problem, as both the data and the read
signal will give the ram enough slack to sample them correctly.
(I could also make the FSM transition on negedge, and leave the RAM
posedge sensitive).
My question is though:
Is option 2 a generally recommended way to solve this problem?
Are there better solutions? how is this done correctly?
(I'm dissatisfied with my solution, since generally, i'll be getting
only half the clock period to stabilize my signals... so it might
become a problem if I would ever need to insert additional logic in
between the data paths.)
Thanks for your comments,
Itay