Add wishbone register
This module registers all signals on a wishbone bus. This increases latency/decreases throughput, but the wishbone cores here are just for management, so that's not really critical. Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
parent
db4c225db5
commit
52bc62814e
1
Makefile
1
Makefile
|
@ -154,6 +154,7 @@ MODULES += uart_tx
|
|||
MODULES += uart_rx
|
||||
MODULES += uart_wb_bridge
|
||||
MODULES += wb_mux
|
||||
MODULES += wb_reg
|
||||
|
||||
.PHONY: test
|
||||
test: $(addsuffix .fst,$(MODULES)) $(addsuffix .synth.fst,$(MODULES))
|
||||
|
|
|
@ -241,6 +241,11 @@ This implements a simple Wishbone mux, allowing a single master to access
|
|||
several slaves. The address decoding is greatly simplified by assigning each
|
||||
slave a (priority-decoded) address bit.
|
||||
|
||||
=== `wb_reg`
|
||||
|
||||
Add a register stage to a wishbone bus. This helps improve timing, but will add
|
||||
a cycle of latency (and decrease throughput).
|
||||
|
||||
== Interfaces
|
||||
|
||||
Throughout this project, a variety of interfaces, some standard and some
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-Only
|
||||
/*
|
||||
* Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
|
||||
*/
|
||||
|
||||
`include "common.vh"
|
||||
|
||||
module wb_reg (
|
||||
input clk, rst,
|
||||
|
||||
output reg s_ack, s_err,
|
||||
input s_cyc, s_stb, s_we,
|
||||
input [ADDR_WIDTH - 1:0] s_addr,
|
||||
input [DATA_WIDTH - 1:0] s_data_write,
|
||||
output reg [DATA_WIDTH - 1:0] s_data_read,
|
||||
|
||||
input m_ack, m_err,
|
||||
output reg m_cyc, m_stb, m_we,
|
||||
output reg [ADDR_WIDTH - 1:0] m_addr,
|
||||
output reg [DATA_WIDTH - 1:0] m_data_write,
|
||||
input [DATA_WIDTH - 1:0] m_data_read
|
||||
);
|
||||
|
||||
parameter ADDR_WIDTH = 16;
|
||||
parameter DATA_WIDTH = 16;
|
||||
|
||||
initial begin
|
||||
s_ack = 0;
|
||||
s_err = 0;
|
||||
m_cyc = 0;
|
||||
m_stb = 0;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_ack <= 0;
|
||||
s_err <= 0;
|
||||
m_cyc <= 0;
|
||||
m_stb <= 0;
|
||||
end else begin
|
||||
s_ack <= m_ack && s_cyc && s_stb;
|
||||
s_err <= m_err && s_cyc && s_stb;
|
||||
m_cyc <= s_cyc && !(m_ack || m_err);
|
||||
m_stb <= s_stb && !(m_ack || m_err);
|
||||
end
|
||||
s_data_read <= m_data_read;
|
||||
m_we <= s_we;
|
||||
m_addr <= s_addr;
|
||||
m_data_write <= s_data_write;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-Only
|
||||
# Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
|
||||
|
||||
import cocotb
|
||||
from cocotb.binary import BinaryValue
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import FallingEdge, RisingEdge, Timer
|
||||
|
||||
from .mdio import wb_read, wb_write, wb_err
|
||||
from .mdio_regs import wb_xfer
|
||||
|
||||
@cocotb.test(timeout_time=50, timeout_unit='us')
|
||||
async def test_reg(reg):
|
||||
reg.clk.value = BinaryValue('Z')
|
||||
reg.rst.value = 0
|
||||
reg.s_cyc.value = 1
|
||||
reg.s_stb.value = 0
|
||||
reg.m_ack.value = 0
|
||||
reg.m_err.value = 0
|
||||
|
||||
await Timer(1)
|
||||
await cocotb.start(Clock(reg.clk, 8, units='ns').start())
|
||||
await FallingEdge(reg.clk)
|
||||
|
||||
master = {
|
||||
'clk': reg.clk,
|
||||
'ack': reg.m_ack,
|
||||
'err': reg.m_err,
|
||||
'cyc': reg.m_cyc,
|
||||
'stb': reg.m_stb,
|
||||
'we': reg.m_we,
|
||||
'addr': reg.m_addr,
|
||||
'data_write': reg.m_data_write,
|
||||
'data_read': reg.m_data_read,
|
||||
}
|
||||
|
||||
slave = {
|
||||
'clk': reg.clk,
|
||||
'ack': reg.s_ack,
|
||||
'err': reg.s_err,
|
||||
'cyc': reg.s_cyc,
|
||||
'stb': reg.s_stb,
|
||||
'we': reg.s_we,
|
||||
'addr': reg.s_addr,
|
||||
'data_write': reg.s_data_write,
|
||||
'data_read': reg.s_data_read,
|
||||
}
|
||||
|
||||
async def resp():
|
||||
await wb_read(master, 0x0123, 0x4567)
|
||||
await wb_write(master, 0x89ab, 0xcdef)
|
||||
await wb_err(master)
|
||||
|
||||
await cocotb.start(resp())
|
||||
|
||||
assert await wb_xfer(slave, 0x0123) == 0x4567
|
||||
await wb_xfer(slave, 0x89ab, 0xcdef)
|
||||
assert await wb_xfer(slave, 0xdead) is None
|
||||
|
||||
reg.rst.value = 1
|
||||
reg.s_cyc.value = 1
|
||||
reg.m_ack.value = 1
|
||||
reg.m_err.value = 1
|
||||
await FallingEdge(reg.clk)
|
||||
assert not reg.m_cyc.value
|
||||
assert not reg.m_stb.value
|
||||
assert not reg.s_ack.value
|
||||
assert not reg.s_err.value
|
Loading…
Reference in New Issue