Add step5.
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| build | ||||
| *.vcd | ||||
| *.gtkw | ||||
| __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