Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Asynchronous FIFO pointer for almost_empty generation

quocviet19501

Newbie level 6
Joined
Aug 21, 2023
Messages
14
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
107
Hi all, I'm doing a systemverilog project in designing an asynchronous FIFO.
My design is fine until I have to customize the read pointer for almost_empty reneration.

Here is my code :

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
module rprt_flag
#(parameter ADDRSIZE = 4)
(
 output logic                  rempty,
 output logic                  almost_rempty,
 output logic   [ADDRSIZE-1:0] raddr,
 input  logic   [ADDRSIZE  :0] g_wprt_syn,
 input  logic                  rclk, rrst_n
 );
 
 logic  [ADDRSIZE:0] rbin;
 logic  [ADDRSIZE:0] rprt;
 logic  [ADDRSIZE:0] rgraynext, rbinnext;
 logic               rempty_val;
 logic               almost_rempty_val;
 
 always_ff @(posedge rclk or negedge rrst_n)
   if (!rrst_n) {rbin, rprt} <= '0;
   else         {rbin, rprt} <= {rbinnext, rgraynext};
 
 assign raddr      = rbin[ADDRSIZE-1:0];
 assign rbinnext   = rbin + {{(ADDRSIZE){1'b0}}, 1'b1};
 assign rgraynext  = (rbinnext>>1) ^ rbinnext;
 assign rempty_val = (rgraynext == g_wprt_syn);
 
 ////////////////TESTING//////////////////////////////////////
 logic [ADDRSIZE:0] rbinnext_val;
 logic [ADDRSIZE:0] rgraynext_val;
 
 assign rbinnext_val      = (rbin + {{(ADDRSIZE){1'b0}}, 1'b1}) -2;
 assign rgraynext_val     = (rbinnext_val>>1) ^ rbinnext_val;
 assign almost_rempty_val = (rgraynext_val  ==  g_wprt_syn);
//////////////////////////////////////////////////////////////
 
 always_ff @(posedge rclk or negedge rrst_n)
   if (!rrst_n) begin
              rempty  <= 1'b1;
              almost_rempty  <= '1;     
   end else begin   
              rempty  <= rempty_val;
              almost_rempty  <= almost_rempty_val;
   end
 
endmodule : rprt_flag


In the testing section I want to make an almost_rempty signal that runs faster than rempty signal 2 clk cycles.
I have tried everything but it did not work.

can anyone siggest an idea how to modify my code.
Thank a lot.

Here is my expected waveform:
1694746293499.png
 
Last edited by a moderator:
Hi,

I don't know about sytem verilog.

But it should be something like this:
[if read_pointer - write_pointer < 2]
Or similar.
(Should work for 2^n buffer size, even in wrap around condition)

Just as a hint...

Klaus
 
Hi,

I don't know about sytem verilog.

But it should be something like this:
[if read_pointer - write_pointer < 2]
Or similar.
(Should work for 2^n buffer size, even in wrap around condition)

Just as a hint...

Klaus
I have tried it but it did not work.
Can you perhaps explain more
 
Many design details are strange. It's a single clock rather than domain crossing dual clock fifo, why does it use gray coded pointers? It's missing features of a complete fifo, e.g. read and write enable, under this conditions, what's the purpose of a fifo at all? I agree with KlausST, almost empty with a margin of 2 can be generated with a pointer offset.
 
Hi,
I have tried it but it did not work
I can´t gain any information from this statement.
An error description should always tell:
"What" did you try?
"how" did you try (test conditions)
"What" did you expect?
and what did not work as expected?

Klaus
 
Hi,

I can´t gain any information from this statement.
An error description should always tell:
"What" did you try?
"how" did you try (test conditions)
"What" did you expect?
and what did not work as expected?

Klaus
sorry for the late response. I have try and I thank I am half way there. Can you still help.
The problem is that when the read pointer = 14, 15 then the write pointer = ? for the almost_rempty to assert
This is my try, correct me if I'm wrong: (read pointer - write pointer < 2) && (write pointer - read pointer > 14).
To be honest, I donot know weather this condition is correct or not. Can you help ?
--- Updated ---

Many design details are strange. It's a single clock rather than domain crossing dual clock fifo, why does it use gray coded pointers? It's missing features of a complete fifo, e.g. read and write enable, under this conditions, what's the purpose of a fifo at all? I agree with KlausST, almost empty with a margin of 2 can be generated with a pointer offset.
The above code is for the read pointer only. My design is a asynchronous FIFO that used in another design. So in order for it to work I have to remove the redundant details such as write enable, full flag.... Since it is a customed FIFO, I got stuck quite a lot. Thank you for replying.
 
Hi
The problem is that when the read pointer = 14, 15 then the write pointer = ? for the almost_rempty to assert
What odes 14, 15 mean?

It shouldn´t be that hard to give all conditions in clear way:
* read pointer:
* write pointer:
* total FIFO size:
* early size:
... maybe more...


Klaus
 
Hi

What odes 14, 15 mean?

It shouldn´t be that hard to give all conditions in clear way:
* read pointer:
* write pointer:
* total FIFO size:
* early size:
... maybe more...


Klaus
when I use your condition for the design. The almost_empty signal asserts the same time as empty signal. It does not assert like the above picture. This is mi updated code. please correct me.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
module rprt_flag
#(parameter ADDRSIZE = 4)
(
 output logic                  rempty,
 output logic                  almost_rempty,
 output logic   [ADDRSIZE-1:0] raddr,
 input  logic   [ADDRSIZE  :0] g_wprt_syn,
 input  logic                  rclk, rrst_n
 );
 
 logic  [ADDRSIZE:0] rbin;
 logic  [ADDRSIZE:0] rbinnext;
 logic               rempty_val;
 logic  [ADDRSIZE:0] b_wprt_syn;
 logic               almost_rempty_val;
 
  always_ff @(posedge rclk or negedge rrst_n) begin
       if (!rrst_n) rbin  <= '0;
       else         rbin  <= rbinnext;
     end
 
 assign raddr      = rbin[ADDRSIZE-1:0];
 assign rbinnext   = rbin + {{(ADDRSIZE){1'b0}}, 1'b1};
 
 //////conver grey code to binary///////////////////////////////
 assign b_wprt_syn[4] = g_wprt_syn[4];
 assign b_wprt_syn[3] = b_wprt_syn[4] ^ g_wprt_syn[3];
 assign b_wprt_syn[2] = b_wprt_syn[3] ^ g_wprt_syn[2];
 assign b_wprt_syn[1] = b_wprt_syn[2] ^ g_wprt_syn[1];
 assign b_wprt_syn[0] = b_wprt_syn[1] ^ g_wprt_syn[0];
////////////////////////////////////////////////////////////////
 
 assign rempty_val = (rbinnext == b_wprt_syn);
 
   always_ff @(posedge rclk or negedge rrst_n)
       if (!rrst_n) begin
              rempty  <= 1'b1;
              almost_rempty <= 1'b1;
             end
       else begin
              rempty  <= rempty_val;
              almost_rempty <= almost_rempty_val;
            end
 
 assign almost_rempty_val = (rbinnext - b_wprt_syn) < 2;
endmodule : rprt_flag


rbinext is the read pointer and b_wprt_syn is the binary write pointer from the write domain (I have converted it from grey code )

[ MODERATOR ACTION: Enclosed code with syntax tags ]
 
Last edited by a moderator:

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top