658bf9df235635147b61b955b675d73ad00afaa5
[gram.git] / gram / frontend / wishbone.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2 # License: BSD
3
4 from math import log2
5
6 from nmigen import *
7 from nmigen.utils import log2_int
8
9 from nmigen_soc import wishbone
10 from nmigen_soc.memory import MemoryMap
11 from lambdasoc.periph import Peripheral
12
13
14 class gramWishbone(Peripheral, Elaboratable):
15 def __init__(self, core, data_width=32, granularity=8):
16 super().__init__(name="wishbone")
17
18 self.native_port = core.crossbar.get_native_port()
19
20 self.ratio = self.native_port.data_width//data_width
21
22 addr_width = log2_int(core.size//(self.native_port.data_width//data_width))
23 self.bus = wishbone.Interface(addr_width=addr_width+log2_int(self.ratio),
24 data_width=data_width, granularity=granularity)
25
26 map = MemoryMap(addr_width=addr_width+log2_int(self.ratio)+log2_int(data_width//granularity),
27 data_width=granularity)
28 self.bus.memory_map = map
29
30 def elaborate(self, platform):
31 m = Module()
32
33 # Write datapath
34 m.d.comb += [
35 self.native_port.wdata.valid.eq(self.bus.cyc & self.bus.stb & self.bus.we),
36 ]
37
38 ratio_bitmask = Repl(1, log2_int(self.ratio))
39
40 sel = Signal.like(self.bus.sel)
41 with m.If(self.bus.sel == 0):
42 m.d.comb += sel.eq(Repl(1, sel.width))
43 with m.Else():
44 m.d.comb += sel.eq(self.bus.sel)
45
46 with m.Switch(self.bus.adr & ratio_bitmask):
47 for i in range(self.ratio):
48 with m.Case(i):
49 m.d.comb += self.native_port.wdata.we.eq(Repl(self.bus.sel, self.bus.granularity//8) << (self.ratio*i))
50
51 with m.Switch(self.bus.adr & ratio_bitmask):
52 for i in range(self.ratio):
53 with m.Case(i):
54 m.d.comb += self.native_port.wdata.data.eq(self.bus.dat_w << (self.bus.data_width*i))
55
56 # Read datapath
57 m.d.comb += [
58 self.native_port.rdata.ready.eq(1),
59 ]
60
61 with m.Switch(self.bus.adr & ratio_bitmask):
62 for i in range(self.ratio):
63 with m.Case(i):
64 m.d.comb += self.bus.dat_r.eq(self.native_port.rdata.data >> (self.bus.data_width*i))
65
66 with m.FSM():
67 with m.State("Send-Cmd"):
68 m.d.comb += [
69 self.native_port.cmd.valid.eq(self.bus.cyc & self.bus.stb),
70 self.native_port.cmd.we.eq(self.bus.we),
71 self.native_port.cmd.addr.eq(self.bus.adr >> log2_int(self.bus.data_width//self.bus.granularity)),
72 ]
73
74 with m.If(self.native_port.cmd.valid & self.native_port.cmd.ready):
75 with m.If(self.bus.we):
76 m.next = "Wait-Write"
77 with m.Else():
78 m.next = "Wait-Read"
79
80 with m.State("Wait-Read"):
81 with m.If(self.native_port.rdata.valid):
82 m.d.comb += self.bus.ack.eq(1)
83 m.next = "Send-Cmd"
84
85 with m.State("Wait-Write"):
86 with m.If(self.native_port.wdata.ready):
87 m.d.comb += self.bus.ack.eq(1)
88 m.next = "Send-Cmd"
89
90 return m