axis_wb_bridge: Use a counter for data phases
This commit is contained in:
parent
a75b77d8e5
commit
9750e841f5
|
@ -13,26 +13,26 @@ The UART protocol uses a request/response format. Each wishbone transaction
|
||||||
corresponds to one request and one response. Each request begins with a command
|
corresponds to one request and one response. Each request begins with a command
|
||||||
byte; an optional, variable-length address; and some data if the request is a
|
byte; an optional, variable-length address; and some data if the request is a
|
||||||
write. Each response begins with a status byte, followed by some data if the
|
write. Each response begins with a status byte, followed by some data if the
|
||||||
request was a read. The following diagram shows a successful read:
|
request was a read. The following diagram shows a successful 16-bit read:
|
||||||
|
|
||||||
++++
|
++++
|
||||||
<script type="WaveDrom">
|
<script type="WaveDrom">
|
||||||
{ signal : [
|
{ signal : [
|
||||||
{ name: "rx", wave: "z34444z....", data: "CMD ADDR0 ADDR1 ADDR2 ADDR3" },
|
{ name: "rx", wave: "z34444z....", data: "CMD ADDR ADDR ADDR ADDR" },
|
||||||
{ name: "tx", wave: "z......655z", data: "STATUS DATA0 DATA1" },
|
{ name: "tx", wave: "z......655z", data: "STATUS DATA DATA" },
|
||||||
],
|
],
|
||||||
config: { hscale: 2 },
|
config: { hscale: 2 },
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
++++
|
++++
|
||||||
|
|
||||||
Similarly, this diagram shows a successful write:
|
Similarly, this diagram shows a successful 32-bit write:
|
||||||
|
|
||||||
++++
|
++++
|
||||||
<script type="WaveDrom">
|
<script type="WaveDrom">
|
||||||
{ signal : [
|
{ signal : [
|
||||||
{ name: "rx", wave: "z3444455z..", data: "CMD ADDR0 ADDR1 ADDR2 ADDR3 DATA0 DATA1" },
|
{ name: "rx", wave: "z3444455z..", data: "CMD ADDR ADDR DATA DATA DATA DATA" },
|
||||||
{ name: "tx", wave: "z........6z", data: "RESP" },
|
{ name: "tx", wave: "z........6z", data: "STATUS" },
|
||||||
],
|
],
|
||||||
config: { hscale: 2 },
|
config: { hscale: 2 },
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ Similarly, this diagram shows a successful write:
|
||||||
++++
|
++++
|
||||||
|
|
||||||
The bridge contains an internal address register that retains its state between
|
The bridge contains an internal address register that retains its state between
|
||||||
different transactions. It possible to reduce the length of requests by
|
different transactions. Requests may send fewer address bytes if the upper bytes
|
||||||
partially modifying the address register.
|
do not need to be modified.
|
||||||
|
|
||||||
=== Requests
|
=== Requests
|
||||||
|
|
||||||
|
@ -124,8 +124,8 @@ follows:
|
||||||
| 7:4 | Reserved | Reserved, do not use.
|
| 7:4 | Reserved | Reserved, do not use.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
Finally, there is a data phase if the request was a read. Data is transmitted
|
Finally, there is a data phase if the request was a successful read. Data is
|
||||||
in big-endian byte order (most-significant byte first).
|
transmitted in little-endian byte order (least-significant byte first).
|
||||||
|
|
||||||
=== Resetting
|
=== Resetting
|
||||||
|
|
||||||
|
|
|
@ -28,23 +28,20 @@ module axis_wb_bridge (
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter ADDR_WIDTH = 32;
|
parameter ADDR_WIDTH = 32;
|
||||||
|
parameter DATA_WIDTH = 16;
|
||||||
generate if (ADDR_WIDTH % 8)
|
generate if (ADDR_WIDTH % 8)
|
||||||
$error("Unsupported ADDR_WIDTH");
|
$error("Unsupported ADDR_WIDTH");
|
||||||
endgenerate
|
endgenerate
|
||||||
/* The data width is not parametric for now */
|
|
||||||
localparam DATA_WIDTH = 16;
|
|
||||||
|
|
||||||
localparam IDLE = 0;
|
localparam IDLE = 0;
|
||||||
localparam ADDR3 = 1;
|
localparam ADDR3 = 1;
|
||||||
localparam ADDR2 = 2;
|
localparam ADDR2 = 2;
|
||||||
localparam ADDR1 = 3;
|
localparam ADDR1 = 3;
|
||||||
localparam ADDR0 = 4;
|
localparam ADDR0 = 4;
|
||||||
localparam DATA1 = 5;
|
localparam DATA = 5;
|
||||||
localparam DATA0 = 6;
|
localparam BUS = 6;
|
||||||
localparam BUS = 7;
|
localparam RESP = 7;
|
||||||
localparam RESP2 = 8;
|
localparam END = 8;
|
||||||
localparam RESP1 = 9;
|
|
||||||
localparam RESP0 = 10;
|
|
||||||
|
|
||||||
reg s_axis_ready_next, m_axis_valid_next;
|
reg s_axis_ready_next, m_axis_valid_next;
|
||||||
reg [7:0] m_axis_data_next;
|
reg [7:0] m_axis_data_next;
|
||||||
|
@ -53,6 +50,7 @@ module axis_wb_bridge (
|
||||||
reg [ADDR_WIDTH - 1:0] wb_addr_next;
|
reg [ADDR_WIDTH - 1:0] wb_addr_next;
|
||||||
reg [DATA_WIDTH - 1:0] wb_data_write_next, wb_data_latch, wb_data_latch_next;
|
reg [DATA_WIDTH - 1:0] wb_data_write_next, wb_data_latch, wb_data_latch_next;
|
||||||
reg [3:0] state, state_next;
|
reg [3:0] state, state_next;
|
||||||
|
reg [2:0] counter, counter_next;
|
||||||
reg overflow_latch, overflow_latch_next, postinc, postinc_next;
|
reg overflow_latch, overflow_latch_next, postinc, postinc_next;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
|
@ -71,6 +69,7 @@ module axis_wb_bridge (
|
||||||
wb_data_latch_next = wb_data_latch;
|
wb_data_latch_next = wb_data_latch;
|
||||||
|
|
||||||
state_next = state;
|
state_next = state;
|
||||||
|
counter_next = counter;
|
||||||
postinc_next = postinc;
|
postinc_next = postinc;
|
||||||
overflow_latch_next = overflow_latch || overflow;
|
overflow_latch_next = overflow_latch || overflow;
|
||||||
|
|
||||||
|
@ -85,13 +84,15 @@ module axis_wb_bridge (
|
||||||
2'd2: state_next = ADDR1;
|
2'd2: state_next = ADDR1;
|
||||||
2'd1: state_next = ADDR0;
|
2'd1: state_next = ADDR0;
|
||||||
2'd0: if (wb_we_next) begin
|
2'd0: if (wb_we_next) begin
|
||||||
state_next = DATA1;
|
state_next = DATA;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = BUS;
|
state_next = BUS;
|
||||||
wb_stb_next = 1;
|
wb_stb_next = 1;
|
||||||
s_axis_ready_next = 0;
|
s_axis_ready_next = 0;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
counter_next = 1;
|
||||||
end
|
end
|
||||||
ADDR3: if (s_axis_valid && s_axis_ready) begin
|
ADDR3: if (s_axis_valid && s_axis_ready) begin
|
||||||
if (ADDR_WIDTH >= 32)
|
if (ADDR_WIDTH >= 32)
|
||||||
|
@ -112,40 +113,38 @@ module axis_wb_bridge (
|
||||||
if (ADDR_WIDTH >= 8)
|
if (ADDR_WIDTH >= 8)
|
||||||
wb_addr_next[7:0] = s_axis_data;
|
wb_addr_next[7:0] = s_axis_data;
|
||||||
if (wb_we) begin
|
if (wb_we) begin
|
||||||
state_next = DATA1;
|
state_next = DATA;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = BUS;
|
state_next = BUS;
|
||||||
wb_stb_next = 1;
|
wb_stb_next = 1;
|
||||||
s_axis_ready_next = 0;
|
s_axis_ready_next = 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
DATA1: if (s_axis_valid && s_axis_ready) begin
|
DATA: if(s_axis_valid && s_axis_ready) begin
|
||||||
wb_data_write_next = { wb_data_write[7:0], s_axis_data };
|
|
||||||
state_next = DATA0;
|
|
||||||
end
|
|
||||||
DATA0: if(s_axis_valid && s_axis_ready) begin
|
|
||||||
wb_data_write_next = { wb_data_write[7:0], s_axis_data };
|
wb_data_write_next = { wb_data_write[7:0], s_axis_data };
|
||||||
|
counter_next = counter - 1;
|
||||||
|
if (!counter) begin
|
||||||
state_next = BUS;
|
state_next = BUS;
|
||||||
wb_stb_next = 1;
|
wb_stb_next = 1;
|
||||||
s_axis_ready_next = 0;
|
s_axis_ready_next = 0;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
BUS: if (wb_ack || wb_err) begin
|
BUS: if (wb_ack || wb_err) begin
|
||||||
wb_stb_next = 0;
|
wb_stb_next = 0;
|
||||||
wb_addr_next[7:0] = wb_addr[7:0] + postinc;
|
wb_addr_next[7:0] = wb_addr[7:0] + postinc;
|
||||||
m_axis_valid_next = 1;
|
m_axis_valid_next = 1;
|
||||||
m_axis_data_next = { 4'b0, overflow_latch_next, 1'b0, wb_err, wb_we };
|
m_axis_data_next = { 4'b0, overflow_latch_next, 1'b0, wb_err, wb_we };
|
||||||
overflow_latch_next = 0;
|
overflow_latch_next = 0;
|
||||||
state_next = wb_we || wb_err ? RESP0 : RESP2;
|
state_next = wb_we || wb_err ? END : RESP;
|
||||||
end
|
end
|
||||||
RESP2: if (m_axis_ready && m_axis_valid) begin
|
RESP: if (m_axis_ready && m_axis_valid) begin
|
||||||
m_axis_data_next = wb_data_latch[15:8];
|
|
||||||
state_next = RESP1;
|
|
||||||
end
|
|
||||||
RESP1: if (m_axis_ready && m_axis_valid) begin
|
|
||||||
m_axis_data_next = wb_data_latch[7:0];
|
m_axis_data_next = wb_data_latch[7:0];
|
||||||
state_next = RESP0;
|
wb_data_latch_next = { 8'bX, wb_data_latch[15:8] };
|
||||||
|
counter_next = counter - 1;
|
||||||
|
if (!counter)
|
||||||
|
state_next = END;
|
||||||
end
|
end
|
||||||
RESP0: if (m_axis_ready && m_axis_valid) begin
|
END: if (m_axis_ready && m_axis_valid) begin
|
||||||
m_axis_valid_next = 0;
|
m_axis_valid_next = 0;
|
||||||
s_axis_ready_next = 1;
|
s_axis_ready_next = 1;
|
||||||
state_next = IDLE;
|
state_next = IDLE;
|
||||||
|
@ -160,6 +159,7 @@ module axis_wb_bridge (
|
||||||
wb_data_write <= wb_data_write_next;
|
wb_data_write <= wb_data_write_next;
|
||||||
wb_data_latch <= wb_data_latch_next;
|
wb_data_latch <= wb_data_latch_next;
|
||||||
postinc <= postinc_next;
|
postinc <= postinc_next;
|
||||||
|
counter <= counter_next;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk, posedge rst) begin
|
always @(posedge clk, posedge rst) begin
|
||||||
|
@ -192,12 +192,10 @@ module axis_wb_bridge (
|
||||||
ADDR2: state_text = "ADDR2";
|
ADDR2: state_text = "ADDR2";
|
||||||
ADDR1: state_text = "ADDR1";
|
ADDR1: state_text = "ADDR1";
|
||||||
ADDR0: state_text = "ADDR0";
|
ADDR0: state_text = "ADDR0";
|
||||||
DATA1: state_text = "DATA1";
|
DATA: state_text = "DATA";
|
||||||
DATA0: state_text = "DATA0";
|
|
||||||
BUS: state_text = "BUS";
|
BUS: state_text = "BUS";
|
||||||
RESP2: state_text = "RESP2";
|
END: state_text = "RESP";
|
||||||
RESP1: state_text = "RESP1";
|
RESP: state_text = "END";
|
||||||
RESP0: state_text = "RESP0";
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
|
@ -124,7 +124,7 @@ async def test_bridge(bridge, in_ratio, out_ratio):
|
||||||
else:
|
else:
|
||||||
await wb_read(wb, addr, data)
|
await wb_read(wb, addr, data)
|
||||||
bridge.overflow.value = 0
|
bridge.overflow.value = 0
|
||||||
await recv_packet(m_axis, (resp, *data.to_bytes(2, 'big')))
|
await recv_packet(m_axis, (resp, *data.to_bytes(2, 'little')))
|
||||||
|
|
||||||
async def write(addr, data, postinc=False, resp=STATUS_WE):
|
async def write(addr, data, postinc=False, resp=STATUS_WE):
|
||||||
await send_packet(s_axis, e.encode(addr, data, postinc), in_ratio)
|
await send_packet(s_axis, e.encode(addr, data, postinc), in_ratio)
|
||||||
|
@ -154,7 +154,7 @@ async def test_bridge(bridge, in_ratio, out_ratio):
|
||||||
await f(0x00000000, 11)
|
await f(0x00000000, 11)
|
||||||
|
|
||||||
# fast back-to-back
|
# fast back-to-back
|
||||||
recv = await cocotb.start(recv_packet(m_axis, (STATUS_WE, 0, 0, 4)))
|
recv = await cocotb.start(recv_packet(m_axis, (STATUS_WE, 0, 4, 0)))
|
||||||
await send_packet(s_axis, e.encode(1, 2))
|
await send_packet(s_axis, e.encode(1, 2))
|
||||||
await wb_write(wb, 1, 2)
|
await wb_write(wb, 1, 2)
|
||||||
await send_packet(s_axis, e.encode(3))
|
await send_packet(s_axis, e.encode(3))
|
||||||
|
|
Loading…
Reference in New Issue