Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable UART #57

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
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
AgamemnonasKyriazis marked this conversation as resolved.
Show resolved Hide resolved
#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