182 lines
3.0 KiB
Python
182 lines
3.0 KiB
Python
|
from migen.fhdl.structure import *
|
||
|
from migen.genlib.misc import *
|
||
|
from migen.genlib.cdc import *
|
||
|
from migen.bus import csr
|
||
|
|
||
|
from miscope.bridges.uart2csr.uart import *
|
||
|
|
||
|
WRITE_CMD = 0x01
|
||
|
READ_CMD = 0x02
|
||
|
CLOSE_CMD = 0x03
|
||
|
|
||
|
class Uart2Csr(Module):
|
||
|
def __init__(self, clk_freq, baud):
|
||
|
# Uart interface
|
||
|
self.rx = Signal()
|
||
|
self.tx = Signal()
|
||
|
|
||
|
# Csr interface
|
||
|
self.csr = csr.Interface(32, 8)
|
||
|
|
||
|
###
|
||
|
|
||
|
uart = Uart(clk_freq, baud)
|
||
|
self.specials +=uart
|
||
|
|
||
|
#
|
||
|
# In/Out
|
||
|
#
|
||
|
self.comb +=[
|
||
|
uart.rx.eq(self.rx),
|
||
|
self.tx.eq(uart.tx)
|
||
|
]
|
||
|
|
||
|
cmd = Signal(8)
|
||
|
cnt = Signal(3)
|
||
|
sr = Signal(32)
|
||
|
burst_cnt = Signal(8)
|
||
|
addr = Signal(32)
|
||
|
data = Signal(8)
|
||
|
|
||
|
#
|
||
|
# Global
|
||
|
#
|
||
|
self.sync +=[
|
||
|
If(fsm.ongoing(fsm.IDLE), cnt.eq(0)
|
||
|
).Elif(uart_rx_ev, cnt.eq(cnt + 1)),
|
||
|
|
||
|
sr.eq(Cat(uart.rx_dat, sr[0:24]))
|
||
|
]
|
||
|
|
||
|
# FSM
|
||
|
fsm = FSM("IDLE",
|
||
|
"GET_BL", "GET_ADDR",
|
||
|
"GET_DATA", "WRITE_CSR",
|
||
|
"READ_CSR", "SEND_DATA")
|
||
|
|
||
|
# State done
|
||
|
get_bl_done = Signal()
|
||
|
get_addr_done = Signal()
|
||
|
get_data_done = Signal()
|
||
|
send_data_done = Signal()
|
||
|
|
||
|
#
|
||
|
# Idle
|
||
|
#
|
||
|
fsm.act(fsm.IDLE,
|
||
|
If(uart.rx_ev and (uart.rx_dat == WRITE_CMD or uart.rx_dat == READ_CMD),
|
||
|
fsm.next_state(fsm.GET_BL)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
self.sync +=[
|
||
|
If(fsm.ongoing(fsm.IDLE) and uart_rx_env,
|
||
|
cmd.eq(uart.rx_dat)
|
||
|
)
|
||
|
|
||
|
]
|
||
|
|
||
|
#
|
||
|
# Get burst length
|
||
|
#
|
||
|
fsm.act(fsm.GET_BL,
|
||
|
If(get_bl_done,
|
||
|
fsm.next_state(fsm.GET_ADDR)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
self.comb += get_bl_done.eq(uart_rx_ev and fsm.ongoing(fsm.GET_BL))
|
||
|
|
||
|
self.sync +=[
|
||
|
If(get_bl_done,
|
||
|
burst_cnt.eq(uart.rx_dat)
|
||
|
)
|
||
|
]
|
||
|
|
||
|
#
|
||
|
# Get address
|
||
|
#
|
||
|
fsm.act(fsm.GET_ADDR,
|
||
|
If(get_addr_done and cmd == WRITE_CMD,
|
||
|
fsm.next_state(fsm.GET_DATA)
|
||
|
).Elif(get_addr_done and cmd == READ_CMD,
|
||
|
fsm.next_state(fsm.READ_CSR)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
self.comb += get_addr_done.eq(uart_rx_ev and rx_cnt == 4 and fsm.ongoing(fsm.GET_ADDR))
|
||
|
|
||
|
self.sync +=[
|
||
|
If(get_addr_done,
|
||
|
addr.eq(sr)
|
||
|
).Elif(write_data_done or send_data_done,
|
||
|
addr.eq(addr + 4)
|
||
|
)
|
||
|
]
|
||
|
|
||
|
#
|
||
|
# Get data
|
||
|
#
|
||
|
fsm.act(fsm.GET_DATA,
|
||
|
If(get_data_done,
|
||
|
fsm.next_state(fsm.IDLE)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
self.comb += get_data_done.eq(uart_rx_ev and fsm.ongoing(fsm.GET_DATA))
|
||
|
|
||
|
self.sync +=[
|
||
|
If(get_data_done,
|
||
|
burst_cnt.eq(burst_cnt-1),
|
||
|
data.eq(uart.rx_dat)
|
||
|
)
|
||
|
]
|
||
|
|
||
|
#
|
||
|
# Write Csr
|
||
|
#
|
||
|
fsm.act(fsm.WRITE_CSR,
|
||
|
If((not burst_cnt),
|
||
|
fsm.next_state(fsm.IDLE)
|
||
|
).Else(fsm.next_state(fsm.GET_DATA))
|
||
|
)
|
||
|
|
||
|
#
|
||
|
# Read Csr
|
||
|
#
|
||
|
fsm.act(fsm.READ_CSR,
|
||
|
fsm.next_state(fsm.SEND_DATA)
|
||
|
)
|
||
|
|
||
|
#
|
||
|
# Send Data
|
||
|
#
|
||
|
fsm.act(fsm.SEND_DATA,
|
||
|
If(send_data_done and (not burst_cnt),
|
||
|
fsm.next_state(fsm.IDLE)
|
||
|
).Elif(send_data_done,
|
||
|
fsm.next_state(fsm.READ_CSR)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
self.comb += [
|
||
|
uart.tx_dat.eq(csr.dat_r),
|
||
|
uart.we.eq(fsm.entering(fsm.SEND_DATA)),
|
||
|
send_data_done.eq(~uart.we or uart.tx_ev)
|
||
|
]
|
||
|
|
||
|
#
|
||
|
# Csr access
|
||
|
#
|
||
|
self.sync +=[
|
||
|
self.csr.adr.eq(addr),
|
||
|
self.csr.dat_w.eq(data),
|
||
|
If(fsm.ongoing(fsm.WRITE_CSR,
|
||
|
self.csr.we.eq(1)
|
||
|
).Else(
|
||
|
self.csr.we.eq(0)
|
||
|
)
|
||
|
]
|
||
|
|
||
|
|