H. R. LEPROFESSEUR  SUBJECTS  SHOP

 SUBJECTS } PROGRAMMING } CODE: verilog, a simple sync fifo

A simple fifo design for understanding concepts. It's good idea is to pack signals in structures and keep them in a common define file. Your code needs to be simple, structured, understandable, commented appropriately, and easy to maintain. You may write assertions in a seperate file annd use module bind mechanism when simulating. Do not put assertions/validation stuff in the design file.

#--------------------------------

#Copyright (c) Harish RAJPUT

#File name: hrfifo.svh

#Description: Common defines used in the code.

#Date: 2023.08.22

//--------------------------------

typedef struct packed { logic clk; logic rst_n; } clkrst_t; // This is clock and active low reset, assumption is that reset is synchronized with respect to this clock.

typedef struct packed { logic [31:0] d; } fdata_t; // This is data packet into the fifo. It may be more comples with more fields.

typedef struct packed { logic w; logic r; } freq_t; // Fifo request signals, read and write enables.

typedef struct packed { logic full; logic empty; logic overrun; logic underrun; logic almostfull; } fresp_t; // Fifo response signals.

`define FF ( q, d, clk ) always_ff @(posedge clk) q <= d; Filp-flop without explicit reset pin, this result in lower area cell.

`define FFR ( q, d, clk, rst_n, RSTV ) always_ff @(posedge clk, negedge rst_n) q <= !rst_n ? RSTV : d; Flip-flop with explicit reset pin.

//--------------------------------

//EoF hrfifo.svh

//--------------------------------

 

//--------------------------------

#Copyright (c) Harish RAJPUT

#File name: hrfifo.sv

#Description: A simple fifo system verilog code.

#Date: 2023.08.22

//--------------------------------

`include "hrfifo.svh"

module hrfifo #(parameter DWIDTH=8, parameter type DTYPE=logic[DWIDTH-1:0], parameter DEPTH=6) ( // DWIDTH is data width of fifo complex data type DTYPE, DEPTH represents how deep is fifo.

input freq_t req_i, // fifo read/write request controls

output fresp_t resp_o, // fifo response signals

input DTYPE wdata_i, // fifo write data

output DTYPE rdata_o, // fifo read data

input clkrst_t cr ); // clock and reset signals

//--------------------------------

//LOCAL SIGNALS

//--------------------------------

localparam PTRWIDTH=$clog2(DEPTH+1-1);

localparam COUNTWIDTH=$clog2(DEPTH+1);

typedef struct packed { logic [PTRWIDTH-1:0] r; logic [pTRWIDTH-1:0] w; } fptr_t; // fifo read and write pointers.

logic [COUNTWIDTH-1:0] count, count_ff;

fresp_t resp, resp_ff; // flopped the outputs.

DTYPE mem[DEPTH-1:0], mem_ff[dEPTH-1:0]; // This example uses register array, you may use actual memory to store fifo data.

fptr_t rptr, rptr_ff;

fptr_t wptr, wptr_ff;

DTYPE rdata, rdata_ff;

logic zeroflag;

//--------------------------------

//COMBO LOGIC

//--------------------------------

always_comb zeroflag = (count_ff==0) || ((count_ff==1) & req_i.r)

always_comb count = count_ff + req_i.w - req_i.r

always_comb resp.almostfull = (count_ff == $unsigned(DEPTH-2)) && req_i.w && !req_i.r) || (count_ff == $unsigned(DEPTH-1)) && !(req_i.r ^ req_i.w);

always_comb resp.full = (count_ff == $unsigned(DEPTH-1)) && req_i.w && !req_i.r) || (count_ff == $unsigned(DEPTH)) && !(req_i.r ^ req_i.w);

always_comb resp.empty = ((count_ff == 1)) && req_i.ren && !req_i.wen) || ((count_ff == 0)) && !(req_i.wen ^ req_i.ren));

always_comb resp.underrun = ((count_ff == 0) && req_i.ren && !resp_ff.overrun);

always_comb resp.overrun = ((count_ff == DEPTH) && req_i.wen && !req_i.ren && !resp_ff.underrrun);

always_comb rdata = (zeroflag && req_i.w) ? wdata : req_i.r ? mem[rdptr_ff] : rdata_ff;

always_comb rptr = req_i.r & !resp.empty ? rptr_ff+1 : !zeroflag && req_i.r && (rptr_ff == $unsigned(DEPTH-2)) ? '0 : rptr_ff;

always_comb wptr = req_i.wen & !resp.full ? wptr_ff+1 : !zeroflag && req_i.w && (wptr_ff == $unsigned(DEPTH-2)) ? '0 : wptr_ff;

always_comb mem[wptr_ff] = (!zeroflag && req_i.w) & ~resp.full ? wdata_i : mem_ff[wptr_ff];

//--------------------------------

//REGISTERS

//--------------------------------

`FF(rdata_ff, rdata, cr.clk)

`FF(mem_ff, mem, cr.clk)

`FFR(resp_ff, resp, cr.clk, cr.rst_n, '0)

`FFR(count_ff, count, cr.clk, cr.rst_n, '0)

`FFR(rptr_ff, rptr, cr.clk, cr.rst_n, '0)

`FFR(wptr_ff, wptr, cr.clk, cr.rst_n, '0)

//--------------------------------

//OUTPUTS

//--------------------------------

assign rdata_o = rdata_ff;

assign resp_o = resp_ff;

//--------------------------------

//EoF hrfifo.sv

//--------------------------------

Please nnote that above code is not validated, leave a short message for errors, comments or anything else at: hr@Leprofesseur.org