Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ibex_demo_system.core
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ targets:
toplevel: top_cw305
tools:
vivado:
part: "xc7a100tftg256-2" # default to a100 part
#part: "xc7a35tftg256-2" # a35 option
part: "xc7a35tftg256-2" # a35 option
parameters:
- SRAMInitFile
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
Expand Down
8 changes: 7 additions & 1 deletion ibex_demo_system_core.core
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ filesets:
- rtl/system/gpio.sv
- rtl/system/pwm.sv
- rtl/system/pwm_wrapper.sv
- rtl/system/uart.sv
- rtl/system/uart_top.v
- rtl/system/uart_rx.v
- rtl/system/uart_tx.v
- rtl/system/sync_fifo.v
- rtl/system/async_fifo.v
- rtl/system/uart.vh
- rtl/system/synchronizer.v
- rtl/system/spi_host.sv
- rtl/system/spi_top.sv
file_type: systemVerilogSource
Expand Down
97 changes: 97 additions & 0 deletions rtl/system/async_fifo.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
`include "synchronizer.v"
`timescale 1ns/1ps

module async_fifo #(
parameter WIDTH = 32, // width of data bus
parameter DEPTH = 16 // depth of FIFO buffer
) (
input wire [WIDTH-1:0] wdata_i,
input wire wclk_i,
input wire rclk_i,
input wire rst_ni,
input wire we_i,
input wire re_i,
output wire [WIDTH-1:0] rdata_o,
output wire full_o,
output wire empty_o
);

localparam ADDR_BITS = $clog2(DEPTH); // address width for buffer

reg [ADDR_BITS:0] w_ptr, r_ptr;
wire [ADDR_BITS:0] w_ptr_gray, r_ptr_gray;

wire [ADDR_BITS:0] w_ptr_next, r_ptr_next;
wire [ADDR_BITS:0] w_ptr_next_gray, r_ptr_next_gray;

wire [ADDR_BITS-1:0] w_addr, r_addr;

wire [ADDR_BITS:0] w_ptr_sync_gray, r_ptr_sync_gray;
reg [ADDR_BITS:0] w_ptr_sync_bin, r_ptr_sync_bin;

reg [WIDTH-1:0] mem [0:DEPTH-1];

assign w_ptr_next = (we_i & ~full_o)? w_ptr + 1'b1 : w_ptr;
assign r_ptr_next = (re_i & ~empty_o)? r_ptr + 1'b1 : r_ptr;

assign w_addr = w_ptr[ADDR_BITS-1:0];
assign r_addr = r_ptr[ADDR_BITS-1:0];

assign w_ptr_gray = w_ptr ^ (w_ptr >> 1);
assign r_ptr_gray = r_ptr ^ (r_ptr >> 1);

assign w_ptr_next_gray = w_ptr_next ^ (w_ptr_next >> 1);
assign r_ptr_next_gray = r_ptr_next ^ (r_ptr_next >> 1);

ff2_sync #(
.WIDTH(ADDR_BITS+1)
) sync_w2r_w_ptr (
.clk_i(rclk_i),
.rst_ni(rst_ni),
.wdata_i(w_ptr_gray),
.rdata_o(w_ptr_sync_gray)
);

ff2_sync #(
.WIDTH(ADDR_BITS+1)
) sync_r2w_r_ptr (
.clk_i(wclk_i),
.rst_ni(rst_ni),
.wdata_i(r_ptr_gray),
.rdata_o(r_ptr_sync_gray)
);

integer i;
always @(*) begin : gray_to_bin_w_ptr
for(i=0; i<ADDR_BITS+1; i = i+1)
w_ptr_sync_bin[i] = ^(w_ptr_sync_gray >> i);
end

always @(*) begin : gray_to_bin_r_ptr
for(i=0; i<ADDR_BITS+1; i = i+1)
r_ptr_sync_bin[i] = ^(r_ptr_sync_gray >> i);
end

always @(posedge wclk_i, negedge rst_ni)
if(~rst_ni)
w_ptr <= 0;
else
w_ptr <= w_ptr_next;

always @(posedge wclk_i) begin : write
if(we_i & ~full_o)
mem[w_addr] <= wdata_i;
end

always @(posedge rclk_i, negedge rst_ni) begin : read
if(~rst_ni)
r_ptr <= 0;
else
r_ptr <= r_ptr_next;
end

assign full_o = w_ptr == {~r_ptr_sync_bin[ADDR_BITS], r_ptr_sync_bin[ADDR_BITS-1:0]};
assign empty_o = r_ptr == w_ptr_sync_bin;
assign rdata_o = mem[r_addr];

endmodule
56 changes: 56 additions & 0 deletions rtl/system/sync_fifo.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
`timescale 1ns/1ps

module sync_fifo #(
parameter WIDTH = 32,
parameter DEPTH = 128
) (
input wire clk_i,
input wire rst_ni,
input wire [WIDTH-1:0] wdata_i,
input wire we_i,
input wire re_i,
output wire [WIDTH-1:0] rdata_o,
output wire full_o,
output wire empty_o
);

localparam ADDR_BITS = $clog2(DEPTH); // address width for buffer

reg [ADDR_BITS:0] w_ptr, r_ptr;
wire [ADDR_BITS:0] w_ptr_next, r_ptr_next;

wire [ADDR_BITS-1:0] w_addr, r_addr;

wire full_next, empty_next;

reg [WIDTH-1:0] mem [0:DEPTH-1];

assign w_ptr_next = (~full_o & we_i)? w_ptr + 1'b1 : w_ptr;
assign r_ptr_next = (~empty_o & re_i)? r_ptr + 1'b1 : r_ptr;

assign full_o = r_ptr == {~w_ptr[ADDR_BITS], w_ptr[ADDR_BITS-1:0]};
assign empty_o = r_ptr == w_ptr;

assign rdata_o = mem[r_addr];

assign w_addr = w_ptr[ADDR_BITS-1:0];
assign r_addr = r_ptr[ADDR_BITS-1:0];

always @(posedge clk_i, negedge rst_ni) begin
if(~rst_ni) begin
w_ptr <= 0;
r_ptr <= 0;
end
else begin
w_ptr <= w_ptr_next;
r_ptr <= r_ptr_next;
end
end

always @(posedge clk_i) begin
if(we_i & ~full_o) begin
mem[w_addr] <= wdata_i;
end
end

endmodule
26 changes: 26 additions & 0 deletions rtl/system/synchronizer.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 2 DFF sync clock domain crossing
* for async fifo queue
*/
`timescale 1ns/1ps

module ff2_sync #(
parameter WIDTH = 32
) (
input wire clk_i,
input wire rst_ni,
input wire [WIDTH-1:0] wdata_i,
output reg [WIDTH-1:0] rdata_o
);

reg [WIDTH-1:0] p0;

always @(posedge clk_i, negedge rst_ni)
if(~rst_ni) begin
p0 <= 0;
rdata_o <= 0;
end
else
{rdata_o, p0} <= {p0, wdata_i};

endmodule
Loading