1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

micropythonでshrike-lite その46

1
Last updated at Posted at 2026-10-10

概要

micropythonでshrike-lite、やってみた。
shrikeで、自作cpuやってみた。
UUUをuartで返す。

8bit CPUの仕様

stackマシーン
stackは、8bitで4個搭載
RAMはゼロ。
命令は、12bit
ROMは、64個
RAMは、0個
プログラムカウンタ(pc) 6bit 1個
アドレスレジスタ 6bit 1個
outレジスタ 8bit 1個
出力は、uart

機械語

ニーモニック 動作 機械語
end 停止 000
push x スタックに数値xxを積む。 2xx
adr x アドレスADRに数値xxを代入。 3xx
ifeq スタックTOPが真ならアドレスADRに飛ぶ。 400
ifne スタックTOPが偽ならアドレスADRに飛ぶ。 401
jmp アドレスADRに飛ぶ。 4FF
out スタックTOPを数値出力。 500
emit スタックTOPを出力。 600
+ スタックTOPをNEXTで加算。 F00
- スタックTOPをNEXTで減算。 F01
* スタックTOPをNEXTで乗算。 F02
/ スタックTOPをNEXTで除算。 F03
% スタックTOPをNEXTで剰余。 F04
= スタックTOPをNEXTでイコール。 F0F
< スタックTOPをNEXTで小さい。 F10
> スタックTOPをNEXTで大きい。 F11
dup スタックTOPを複写。 F20
drop スタックTOPを廃棄。 F21

手順

投入するプログラム

UUUを繰り返し、印字する。

0:  push 'U'
1:  emit
2:  push 'U'
3:  emit
4:  push 'U'
5:  emit
6:  push '\r'
7:  emit
8:  push '\n'
9:  emit
10:  adr 0
11:  jmp


top.vを、書く。

top.v

(* top *) module top #(parameter CLK = 50_000_000, parameter BAUD_RATE = 115200) (
    (* iopad_external_pin, clkbuf_inhibit *) input clk,
    (* iopad_external_pin *) output clk_en,
    (* iopad_external_pin *) input rst,
    (* iopad_external_pin *) input rx,
    (* iopad_external_pin *) output tx,
    (* iopad_external_pin *) output tx_en,
    (* iopad_external_pin *) output led,
    (* iopad_external_pin *) output led_en
);
	localparam CNT_MS = CLK / 200 - 1;
	reg [31:0] timer_cnt;
	reg timer_done;
	reg [3:0] state = 4'd0;
	reg flag = 1'b0;
	reg [7:0] q0,
		q1,
		q2,
		q3;
	reg [6:0] pc;
	reg [6:0] adr;
	reg [7:0] out;
	reg [11:0] code;
	wire tx_busy;
	wire [3:0] op = code[11:8];
	wire [7:0] opland = code[7:0];
	assign clk_en = 1'b1;
	assign tx_en = 1'b1;
	assign led_en = 1'b1;
	assign led = flag;
	uart_tx #(.CLK_FREQ(CLK), .BAUD_RATE(BAUD_RATE))
		ut (.clk(clk), .rst(rst), .tx_start(flag), .tx_data(out), .tx(tx), .tx_busy(tx_busy));
	initial
	begin
		$monitor("pc: %d busy: %d out: %s flag: %d", pc, tx_busy, out, flag);
	end
	always @(*)
	begin
		case (pc)
		7'd0: code = 12'h2_55; // PUSH 'U'
		7'd1: code = 12'h6_00; // emit
		7'd2: code = 12'h2_55; // PUSH 'U'
		7'd3: code = 12'h6_00; // emit
		7'd4: code = 12'h2_55; // PUSH 'U'
		7'd5: code = 12'h6_00; // emit
		7'd6: code = 12'h2_0D; // PUSH 0D (\r)
		7'd7: code = 12'h6_00; // emit
		7'd8: code = 12'h2_0A; // PUSH 0A (\n)
		7'd9: code = 12'h6_00; // emit
		7'd10: code = 12'h3_00; // ADR 0
		7'd11: code = 12'h4_FF; // JMP
		
		default: code = 12'h0_00;
		endcase
	end
	always @(posedge clk or posedge rst) 
	begin
		if (rst) 
		begin
			timer_cnt <= 32'd0;
			timer_done <= 1'b0;
		end 
		else 
		begin
			if (timer_cnt >= CNT_MS) 
			begin
				timer_cnt <= 32'd0;
				timer_done <= 1'b1;
			end 
			else 
			begin
				timer_cnt <= timer_cnt + 1'b1;
				timer_done <= 1'b0;
			end
		end
	end
	always @(posedge clk or posedge rst) 
	begin
		if (rst)
		begin
			q0 <= 8'd0;
			q1 <= 8'd0;
			q2 <= 8'd0;
			q3 <= 8'd0;
			adr <= 0;
			out <= 0;
			pc <= 0;
			state <= 4'd0;
			flag <= 1'b0;
		end
		else
		begin
			case (op)
			4'h0: // HALT
				pc <= pc;
			4'h2: // PUSH
			begin
				q3 <= q2; q2 <= q1; q1 <= q0;
				q0 <= opland;
				pc <= pc + 1;
			end
			4'h3: // ADR
			begin
				adr <= opland[6:0];
				pc <= pc + 1;
			end
			4'h4: // IF
			begin
				case (opland)
				8'h00: // JEQ
				begin
					if (q0 == 8'd0)
						pc <= adr;
					else
						pc <= pc + 1;
					q0 <= q1; q1 <= q2; q2 <= q3; q3 <= 8'd0;
				end
				8'h01: // JNE
				begin
					if (q0 == 8'd1)
						pc <= adr;
					else
						pc <= pc + 1;
					q0 <= q1; q1 <= q2; q2 <= q3; q3 <= 8'd0;
				end
				8'hFF: // JMP
					pc <= adr;
				default:
					pc <= pc + 1;
				endcase
			end
			4'h5: // OUT
			begin
				case (state)
				4'h0:
				begin
					if (q0 > 9)
					begin
						out <= q0 / 10 + 48;
						flag <= 1'b1;
						state <= 4'h1;
					end
					else
					begin
						state <= 4'h3;
					end
				end
				4'h1:
				begin
					if (tx_busy)
					begin
						flag <= 1'b0;
						state <= 4'h2;
					end
				end
				4'h2:
				begin
					if (!tx_busy)
					begin
						state <= 4'h3;
					end
				end
				4'h3:
				begin
					out <= q0 % 10 + 48;
					q0 <= q1; q1 <= q2; q2 <= q3; q3 <= 8'd0;
					flag <= 1'b1;
					state <= 4'h4;
				end
				4'h4:
				begin
					if (tx_busy)
					begin
						flag <= 1'b0;
						state <= 4'h5;
					end
				end
				4'h5:
				begin
					if (!tx_busy)
					begin
						state <= 4'h6;
					end
				end
				4'h6:
				begin
					if (timer_done) 
					begin
						pc <= pc + 1;
						state <= 4'h0;
					end
				end
				default:
					state <= 4'h0;
				endcase
			end
			4'h6: // emit
			begin
				case (state)
				4'h0:
				begin
					out <= q0;
					q0 <= q1; q1 <= q2; q2 <= q3; q3 <= 8'd0;
					flag <= 1'b1;
					state <= 4'h1;
				end
				4'h1:
				begin
					if (tx_busy)
					begin
						flag <= 1'b0;
						state <= 4'h2;
					end
				end
			    4'h2:
				begin
					if (!tx_busy)
					begin
						state <= 4'h3;
					end
				end
				4'h3:
				begin
					if (timer_done) 
					begin
						pc <= pc + 1;
						state <= 4'h0;
					end
				end
				default:
					state <= 4'h0;
				endcase
			end
			4'hF:
			begin
				case (opland)
				8'h00: begin q0 <= q1 + q0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // +
				8'h01: begin q0 <= q1 - q0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // -
				//8'h02: begin q0 <= q1 * q0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // *
				//8'h03: begin q0 <= (q0 != 0) ? q1 / q0 : 8'd0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // /
				8'h04: begin q0 <= (q0 != 0) ? q1 % q0 : 8'd0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // mod
				8'h0F: begin q0 <= (q1 == q0) ? 8'd1 : 8'd0; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // =
				//8'h10: begin q0 <= (q1 < q0)  ? 8'd1 : 8'd0;  q1 <= q2; q2 <= q3; q3 <= 8'd0; end // <
				//8'h11: begin q0 <= (q1 > q0)  ? 8'd1 : 8'd0;  q1 <= q2; q2 <= q3; q3 <= 8'd0; end // >
				8'h20: begin q3 <= q2; q2 <= q1; q1 <= q0; end // dup
				8'h21: begin q0 <= q1; q1 <= q2; q2 <= q3; q3 <= 8'd0; end // drop
				default: ;
				endcase
				pc <= pc + 1;
			end
			default:
				pc <= pc + 1;
			endcase
		end
	end
endmodule




テストベンチ結果

image.png

Resource Report

####   Resource Utilization Report   ####

    Top level module name: top

    Resource usage:

        CLB LUT5s:    306/1120 (27.32%)
            Lut5:                          306 (27.32%)
            Lut5 for Shift-register:       0 (0.00%)
            Lut5 for Distributed memory:   0 (0.00%)

        FFs:    112
        CLB FFs: 110/1120 (9.82%)
        IOB FFs: 2/736 (0.27%)

        CLBs:      51/140 (36.43%)
        Tiles:     1/1 (100.00%)

        RTL Input ports:     2 
        RTL Output ports:    5 
        GPIOs:               3/19 (15.79%)

        PLLs:        0/1 (0.00%)
        OSCs:        1/1 (100.00%)
        4k BRAMs:    0/8 (0.00%)

        1 Clock
           Clock 0: net   276, clk, Fanout: 44 CLBs
           Total 1 unique clocks

####   Resource Utilization Complete   ####

TILE-REQ:		0		0		0		1

### Total FPGA resources from current floorplan: ###
                       184 IOBs
                       140 Logic 6-LUT CLBs
                              40 CLBs support RAM/SR

Usage of Logic CLBs is 36.4%.
    Logic-Memory CLB for RAM/Shift-Register is 0.0%.
Usage of LUTs is 35.9%.
    dual-LUTs is 18.9%.
Usage of FF is 16.8%.
    dual-FF is 2.9%.
Usage of IO CLB is 2.2%.

main.pyを書く。


from machine import UART, Pin
import time
import shrike
import uselect

shrike.reset()
shrike.flash("fizz3.bin")

reset_pin = Pin(2, Pin.OUT, value = 0)
uart = UART(0, baudrate = 115200, tx = Pin(0), rx = Pin(1), rxbuf = 512)
print("port open")
reset_pin.value(1)
time.sleep(0.5)
reset_pin.value(0)
print("reset")

def send(value):
	uart.write(bytes([value]))

def reset():
	print("reset")
	reset_pin.value(1)
	time.sleep(0.5)
	reset_pin.value(0)

def resv():
	if uart.any():
		reply = uart.read(1)[0]
		print(reply, chr(reply))

def line():
	while True:
		time.sleep(0.1)
		if uart.any():
			reply = uart.readline()
			print(reply)

def test():
	while True:
		time.sleep(0.01)
		if uart.any():
			reply = uart.read(1)[0]
			print(chr(reply), end="")




実行結果

>shrike0
Port open ok
[shrike_flash] FPGA reset done
[shrike_flash] FPGA reset done  Starting FPGA flash...
[shrike_fpga] flashing: fizz3.bin
[shrike_flash] FPGA programming done.
port open
reset
MicroPython v1.26.0-preview.527.g599f545a3.dirty on 2025-10-11; Vicharak Shrike FPGA with RP2040
Type "help()" for more information.
test()
>>> test()
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU
UUU

2週間、詰んで、学んだこと。

  • micropythonが、処理が追い付かない。fpgaでdelay入れる。5MHz/200で送ってる。
  • fpgaが、これ以上、ロジック増やすと入らない。フルスペックのCPUが書けない。Bramに逃がすと、どうなるか。試さないといけない。

以上。

1
0
15

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?