Skip to content

Commit

Permalink
DEM-UART: Initial implementation for FIFOs
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasLeyk committed Oct 12, 2018
1 parent 8d9016d commit 6be0a48
Show file tree
Hide file tree
Showing 3 changed files with 546 additions and 1 deletion.
116 changes: 116 additions & 0 deletions modules/dem_uart/common/fifo_singleclock_fwft.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/* Copyright (c) 2017 by the author(s)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* =============================================================================
*
* Synchronous First-Word Fall-Through (FWFT) FIFO
*
* This FIFO implementation wraps the FIFO with standard read characteristics
* to have first-word fall-through read characteristics.
*
* Author(s):
* Philipp Wagner <[email protected]>
*/

module fifo_singleclock_fwft #(
parameter WIDTH = 8,
parameter DEPTH = 32,
parameter PROG_FULL = (DEPTH / 2)
)(
input clk,
input rst,

input [(WIDTH-1):0] din,
input wr_en,
output full,
output prog_full,

output reg [(WIDTH-1):0] dout,
input rd_en,
output empty,

output [$clog2(DEPTH)-1:0] count
);

reg fifo_valid, middle_valid, dout_valid;
reg [(WIDTH-1):0] middle_dout;

wire [(WIDTH-1):0] fifo_dout;
wire fifo_empty, fifo_rd_en;
wire will_update_middle, will_update_dout;

// synchronous FIFO with standard (non-FWFT) read characteristics
fifo_singleclock_standard
#(.WIDTH(WIDTH),
.DEPTH(DEPTH),
.PROG_FULL(PROG_FULL))
u_fifo (
.rst(rst),
.clk(clk),
.rd_en(fifo_rd_en),
.dout(fifo_dout),
.empty(fifo_empty),
.wr_en(wr_en),
.din(din),
.full(full),
.prog_full(prog_full),
.count(count)
);

// create FWFT FIFO out of non-FWFT FIFO
// public domain code from Eli Billauer
// see http://www.billauer.co.il/reg_fifo.html
assign will_update_middle = fifo_valid && (middle_valid == will_update_dout);
assign will_update_dout = (middle_valid || fifo_valid) && (rd_en || !dout_valid);
assign fifo_rd_en = (!fifo_empty) && !(middle_valid && dout_valid && fifo_valid);
assign empty = !dout_valid;

always_ff @(posedge clk) begin
if (rst) begin
fifo_valid <= 0;
middle_valid <= 0;
dout_valid <= 0;
dout <= 0;
middle_dout <= 0;
end else begin
if (will_update_middle)
middle_dout <= fifo_dout;

if (will_update_dout)
dout <= middle_valid ? middle_dout : fifo_dout;

if (fifo_rd_en)
fifo_valid <= 1;
else if (will_update_middle || will_update_dout)
fifo_valid <= 0;

if (will_update_middle)
middle_valid <= 1;
else if (will_update_dout)
middle_valid <= 0;

if (will_update_dout)
dout_valid <= 1;
else if (rd_en)
dout_valid <= 0;
end
end

endmodule
111 changes: 111 additions & 0 deletions modules/dem_uart/common/fifo_singleclock_standard.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* Copyright (c) 2017 by the author(s)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* =============================================================================
*
* Synchronous Standard FIFO (one clock)
*
* The memory block in this FIFO is following the "RAM HDL Coding Guidelines"
* of Xilinx (UG901) to enable placing the FIFO memory into block ram during
* synthesis.
*
* Author(s):
* Philipp Wagner <[email protected]>
*/

module fifo_singleclock_standard #(
parameter WIDTH = 8,
parameter DEPTH = 32,
parameter PROG_FULL = DEPTH / 2
)(
input clk,
input rst,

input [(WIDTH-1):0] din,
input wr_en,
output full,
output prog_full,

output reg [(WIDTH-1):0] dout,
input rd_en,
output empty,

output [$clog2(DEPTH) - 1:0] count
);
localparam AW = $clog2(DEPTH);

// ensure that parameters are set to allowed values
initial begin
if ((1 << $clog2(DEPTH)) != DEPTH) begin
$fatal("fifo_singleclock_standard: the DEPTH must be a power of two.");
end
end

reg [AW-1:0] wr_addr;
reg [AW-1:0] rd_addr;
wire fifo_read;
wire fifo_write;
reg [AW-1:0] rd_count;

// generate control signals
assign empty = (rd_count[AW-1:0] == 0);
assign prog_full = (rd_count[AW-1:0] >= PROG_FULL);
assign full = (rd_count[AW-1:0] == (DEPTH-1));
assign fifo_read = rd_en & ~empty;
assign fifo_write = wr_en & ~full;
assign count = rd_count;

// address logic
always_ff @(posedge clk) begin
if (rst) begin
wr_addr[AW-1:0] <= 'd0;
rd_addr[AW-1:0] <= 'b0;
rd_count[AW-1:0] <= 'b0;
end else begin
if (fifo_write & fifo_read) begin
wr_addr[AW-1:0] <= wr_addr[AW-1:0] + 'd1;
rd_addr[AW-1:0] <= rd_addr[AW-1:0] + 'd1;
end else if (fifo_write) begin
wr_addr[AW-1:0] <= wr_addr[AW-1:0] + 'd1;
rd_count[AW-1:0]<= rd_count[AW-1:0] + 'd1;
end else if (fifo_read) begin
rd_addr[AW-1:0] <= rd_addr[AW-1:0] + 'd1;
rd_count[AW-1:0]<= rd_count[AW-1:0] - 'd1;
end
end
end

// generic dual-port, single clock memory
reg [WIDTH-1:0] ram [DEPTH-1:0];

// write
always_ff @(posedge clk) begin
if (fifo_write) begin
ram[wr_addr] <= din;
end
end

// read
always_ff @(posedge clk) begin
if (fifo_read) begin
dout <= ram[rd_addr];
end
end
endmodule
Loading

0 comments on commit 6be0a48

Please sign in to comment.