Add step5.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
build
|
build
|
||||||
*.vcd
|
*.vcd
|
||||||
|
*.gtkw
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|||||||
43
05_register_bank/bench.py
Normal file
43
05_register_bank/bench.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from amaranth import *
|
||||||
|
from amaranth.sim import *
|
||||||
|
|
||||||
|
from soc import SOC
|
||||||
|
|
||||||
|
soc = SOC()
|
||||||
|
|
||||||
|
sim = Simulator(soc)
|
||||||
|
|
||||||
|
prev_clk = 0
|
||||||
|
|
||||||
|
def proc():
|
||||||
|
while True:
|
||||||
|
global prev_clk
|
||||||
|
clk = yield soc.slow_clk
|
||||||
|
if prev_clk == 0 and prev_clk != clk:
|
||||||
|
print("pc={}".format((yield soc.pc)))
|
||||||
|
print("instr={:#032b}".format((yield soc.instr)))
|
||||||
|
print("LEDS = {:05b}".format((yield soc.leds)))
|
||||||
|
if (yield soc.isALUreg):
|
||||||
|
print("ALUreg rd={} rs1={} rs2={} funct3={}".format(
|
||||||
|
(yield soc.rdId), (yield soc.rs1Id), (yield soc.rs2Id),
|
||||||
|
(yield soc.funct3)))
|
||||||
|
if (yield soc.isALUimm):
|
||||||
|
print("ALUimm rd={} rs1={} imm={} funct3={}".format(
|
||||||
|
(yield soc.rdId), (yield soc.rs1Id), (yield soc.Iimm),
|
||||||
|
(yield soc.funct3)))
|
||||||
|
if (yield soc.isLoad):
|
||||||
|
print("LOAD")
|
||||||
|
if (yield soc.isStore):
|
||||||
|
print("STORE")
|
||||||
|
if (yield soc.isSystem):
|
||||||
|
print("SYSTEM")
|
||||||
|
break
|
||||||
|
yield
|
||||||
|
prev_clk = clk
|
||||||
|
|
||||||
|
sim.add_clock(1e-6)
|
||||||
|
sim.add_sync_process(proc)
|
||||||
|
|
||||||
|
with sim.write_vcd('bench.vcd', 'bench.gtkw', traces=soc.ports):
|
||||||
|
# Let's run for a quite long time
|
||||||
|
sim.run_until(2, )
|
||||||
38
05_register_bank/blink.py
Normal file
38
05_register_bank/blink.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from amaranth import *
|
||||||
|
from amaranth_boards.arty_a7 import *
|
||||||
|
|
||||||
|
from soc import SOC
|
||||||
|
|
||||||
|
# A platform contains board specific information about FPGA pin assignments,
|
||||||
|
# toolchain and specific information for uploading the bitfile.
|
||||||
|
platform = ArtyA7_35Platform(toolchain="Symbiflow")
|
||||||
|
|
||||||
|
# We need a top level module
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
# This is the instance of our SOC
|
||||||
|
soc = SOC()
|
||||||
|
|
||||||
|
# The SOC is turned into a submodule (fragment) of our top level module.
|
||||||
|
m.submodules.soc = soc
|
||||||
|
|
||||||
|
# The platform allows access to the various resources defined by the board
|
||||||
|
# definition from amaranth-boards.
|
||||||
|
led0 = platform.request('led', 0)
|
||||||
|
led1 = platform.request('led', 1)
|
||||||
|
led2 = platform.request('led', 2)
|
||||||
|
led3 = platform.request('led', 3)
|
||||||
|
rgb = platform.request('rgb_led')
|
||||||
|
|
||||||
|
# We connect the SOC leds signal to the various LEDs on the board.
|
||||||
|
m.d.comb += [
|
||||||
|
led0.o.eq(soc.leds[0]),
|
||||||
|
led1.o.eq(soc.leds[1]),
|
||||||
|
led1.o.eq(soc.leds[2]),
|
||||||
|
led1.o.eq(soc.leds[3]),
|
||||||
|
rgb.r.o.eq(soc.leds[4]),
|
||||||
|
]
|
||||||
|
|
||||||
|
# To generate the bitstream, we build() the platform using our top level
|
||||||
|
# module m.
|
||||||
|
platform.build(m, do_program=False)
|
||||||
135
05_register_bank/soc.py
Normal file
135
05_register_bank/soc.py
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import sys
|
||||||
|
from amaranth import *
|
||||||
|
|
||||||
|
from clockworks import Clockworks
|
||||||
|
|
||||||
|
class SOC(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.leds = Signal(5)
|
||||||
|
|
||||||
|
# Signals in this list can easily be plotted as vcd traces
|
||||||
|
self.ports = []
|
||||||
|
|
||||||
|
def elaborate(self, platform):
|
||||||
|
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
cw = Clockworks(slow=21)
|
||||||
|
m.submodules.cw = cw
|
||||||
|
|
||||||
|
# Instruction sequence to be executed
|
||||||
|
sequence = [
|
||||||
|
# 24 16 8 0
|
||||||
|
# .......|.......|.......|.......|
|
||||||
|
#R rs2 rs1 f3 rd op
|
||||||
|
#I imm rs1 f3 rd op
|
||||||
|
#S imm rs2 rs1 f3 imm op
|
||||||
|
# ......|....|....|..|....|......|
|
||||||
|
0b00000000000000000000000000110011, # R add x0, x0, x0
|
||||||
|
0b00000000000000000000000010110011, # R add x1, x0, x0
|
||||||
|
0b00000000000100001000000010010011, # I addi x1, x1, 1
|
||||||
|
0b00000000000100001000000010010011, # I addi x1, x1, 1
|
||||||
|
0b00000000000100001000000010010011, # I addi x1, x1, 1
|
||||||
|
0b00000000000100001000000010010011, # I addi x1, x1, 1
|
||||||
|
0b00000000000000001010000100000011, # I lw x2, 0(x1)
|
||||||
|
0b00000000000100010010000000100011, # S sw x2, 0(x1)
|
||||||
|
0b00000000000100000000000001110011 # S ebreak
|
||||||
|
]
|
||||||
|
|
||||||
|
# Program counter
|
||||||
|
pc = Signal(32)
|
||||||
|
|
||||||
|
# Current instruction
|
||||||
|
instr = Signal(32, reset=0b0110011)
|
||||||
|
|
||||||
|
# Instruction memory initialised with above 'sequence'
|
||||||
|
mem = Array([Signal(32, reset=x) for x in sequence])
|
||||||
|
|
||||||
|
# Register bank
|
||||||
|
regs = Array([Signal(32) for x in range(32)])
|
||||||
|
rs1 = Signal(32)
|
||||||
|
rs2 = Signal(32)
|
||||||
|
|
||||||
|
writeBackData = C(0)
|
||||||
|
writeBackEn = C(0)
|
||||||
|
|
||||||
|
# Opcode decoder
|
||||||
|
isALUreg = (instr[0:7] == 0b0110011)
|
||||||
|
isALUimm = (instr[0:7] == 0b0010011)
|
||||||
|
isBranch = (instr[0:7] == 0b1100011)
|
||||||
|
isJALR = (instr[0:7] == 0b1100111)
|
||||||
|
isJAL = (instr[0:7] == 0b1101111)
|
||||||
|
isAUIPC = (instr[0:7] == 0b0010111)
|
||||||
|
isLUI = (instr[0:7] == 0b0110111)
|
||||||
|
isLoad = (instr[0:7] == 0b0000011)
|
||||||
|
isStore = (instr[0:7] == 0b0100011)
|
||||||
|
isSystem = (instr[0:7] == 0b1110011)
|
||||||
|
|
||||||
|
# Immediate format decoder
|
||||||
|
Uimm = (Cat(Repl(0, 12), instr[12:32]))
|
||||||
|
Iimm = (Cat(instr[20:31], Repl(instr[31], 21)))
|
||||||
|
Simm = (Cat(instr[7:12], Cat(instr[25:31], Repl(instr[31], 21)))),
|
||||||
|
Bimm = (Cat(0, Cat(instr[8:12], Cat(instr[25:31], Cat(
|
||||||
|
instr[7], Repl(instr[31], 20))))))
|
||||||
|
Jimm = (Cat(0, Cat(instr[21:31], Cat(instr[20], Cat(
|
||||||
|
instr[12:20], Repl(instr[31], 12))))))
|
||||||
|
|
||||||
|
# Register addresses decoder
|
||||||
|
rs1Id = (instr[15:20])
|
||||||
|
rs2Id = (instr[20:25])
|
||||||
|
rdId = ( instr[7:12])
|
||||||
|
|
||||||
|
# Function code decdore
|
||||||
|
funct3 = (instr[12:15])
|
||||||
|
funct7 = (instr[25:32])
|
||||||
|
|
||||||
|
# Data write back
|
||||||
|
with m.If(writeBackEn & (rdId != 0)):
|
||||||
|
m.d.slow += regs[rdId].eq(writeBackData)
|
||||||
|
|
||||||
|
# Main state machine
|
||||||
|
with m.FSM(reset="FETCH_INSTR") as fsm:
|
||||||
|
# Assign important signals to LEDS
|
||||||
|
m.d.comb += self.leds.eq(Mux(isSystem, 31, (1 << fsm.state)))
|
||||||
|
with m.State("FETCH_INSTR"):
|
||||||
|
m.d.slow += instr.eq(mem[pc])
|
||||||
|
m.next = "FETCH_REGS"
|
||||||
|
with m.State("FETCH_REGS"):
|
||||||
|
m.d.slow += [
|
||||||
|
rs1.eq(regs[rs1Id]),
|
||||||
|
rs2.eq(regs[rs2Id])
|
||||||
|
]
|
||||||
|
m.next = "EXECUTE"
|
||||||
|
with m.State("EXECUTE"):
|
||||||
|
m.d.slow += pc.eq(pc + 1)
|
||||||
|
m.next = "FETCH_INSTR"
|
||||||
|
|
||||||
|
|
||||||
|
# Export signals for simulation
|
||||||
|
def export(signal, name):
|
||||||
|
if type(signal) is not Signal:
|
||||||
|
newsig = Signal(signal.shape(), name = name)
|
||||||
|
m.d.comb += newsig.eq(signal)
|
||||||
|
else:
|
||||||
|
newsig = signal
|
||||||
|
self.ports.append(newsig)
|
||||||
|
setattr(self, name, newsig)
|
||||||
|
|
||||||
|
if platform is None:
|
||||||
|
export(ClockSignal("slow"), "slow_clk")
|
||||||
|
export(pc, "pc")
|
||||||
|
export(instr, "instr")
|
||||||
|
export(isALUreg, "isALUreg")
|
||||||
|
export(isALUimm, "isALUimm")
|
||||||
|
export(isLoad, "isLoad")
|
||||||
|
export(isStore, "isStore")
|
||||||
|
export(isSystem, "isSystem")
|
||||||
|
export(rdId, "rdId")
|
||||||
|
export(rs1Id, "rs1Id")
|
||||||
|
export(rs2Id, "rs2Id")
|
||||||
|
export(Iimm, "Iimm")
|
||||||
|
export(funct3, "funct3")
|
||||||
|
|
||||||
|
return m
|
||||||
Reference in New Issue
Block a user