MiniCPUのアセンブラでサブルーチンコール
概要 †
- 「MiniCPUとI2Cバスの接続」の ram.v の手順をほとんどそのまま、サブルーチンにした例です。I2C操作手順を書いたデータ列の、一つ前のアドレスに、そのデータの大きさ(ワード数)を書いたものをまとめます。データの大きさを書いたアドレスをPUSH命令を使ってサブルーチン SubI2C1に伝えます。操作手順とその大きさを複数用意して、このサブルーチン SubI2C1に引き渡すことにより、様々なI2Cデバイスの操作を行うことができます。
verilog †
- MiniCPUとI2Cバスの接続」の ram.v を以下の ram.v で置き換えて動かします。
- ram.v
module ram(clk, load, addr, d, q
);
parameter DWIDTH=16, AWIDTH=12, WORDS=4096;
input clk, load;
input [AWIDTH-1:0] addr;
input [DWIDTH-1:0] d;
output [DWIDTH-1:0] q;
reg [DWIDTH-1:0] q;
reg [DWIDTH-1:0] mem [WORDS-1:0];
always @(posedge clk)
begin
if(load) mem[addr] <= d;
q <= mem[addr];
end
integer i;
initial begin
for(i=0; i<WORDS; i=i+1)
mem[i]=12'h000;
// Subroutine calling by the mini CPU.
mem[8'h00] = 16'h1021; // PUSHI Sub1Data // push arg1
mem[8'h01] = 16'h1003; // PUSHI Rtn1 // push the return address
mem[8'h02] = 16'h4005; // JMP SubI2C1 // call the subroutine
mem[8'h03] = 16'h0000; // Rtn1: HALT // the return address
mem[8'h04] = 16'h0000; //
mem[8'h05] = 16'h201D; // SubI2C1: PUSH LblJMP // subroutine. the 1st step to make the return instruction
mem[8'h06] = 16'hF006; // BOR // make the return instruction using arg1 and the jump instruction
mem[8'h07] = 16'h301C; // POP RtnSub1 // save the return instruction
mem[8'h08] = 16'h301E; // POP Sub1Data2 // save the arg1
mem[8'h09] = 16'h201E; // PUSH Sub1Data2
mem[8'h0A] = 16'h1001; // PUSHI 1
mem[8'h0B] = 16'hF000; // ADD
mem[8'h0C] = 16'h301F; // POP Sub1SA
mem[8'h0D] = 16'h1000; // PUSHI 0
mem[8'h0E] = 16'h3020; // POP i
mem[8'h0F] = 16'h2020; // L1 PUSH i
mem[8'h10] = 16'h201F; // PUSH Sub1SA
mem[8'h11] = 16'hF000; // ADD
mem[8'h12] = 16'h7000; // LD ... Sub1S[i];
mem[8'h13] = 16'hE000; // OUT ... print(Sub1S[i]) ;
mem[8'h14] = 16'h2020; // PUSH i;
mem[8'h15] = 16'h1001; // PUSHI 1
mem[8'h16] = 16'hF000; // ADD
mem[8'h17] = 16'h3020; // POP i
mem[8'h18] = 16'h2020; // PUSH i
mem[8'h19] = 16'h2021; // PUSH Sub1Data
mem[8'h1A] = 16'hF001; // SUB
mem[8'h1B] = 16'h600F; // JNZ L1: if(i<n) goto L1;
mem[8'h1C] = 16'h0000; // RtnSub1: JMP // return
mem[8'h1D] = 16'h4000; // LblJMP: 0x4000
mem[8'h1E] = 16'h0000; // Sub1Data2:
mem[8'h1F] = 16'h0000; // Sub1SA:
mem[8'h20] = 16'h0000; // i:
//
// data for controlling i2c
// (MSB) ...... scl, sda (LSB)
mem[8'h21] = 16'h0076; // Sub1Data: 0x76 ... 0x88-0x12
mem[8'h22] = 16'h0003; // Sub1S: 11
mem[8'h23] = 16'h0002; // 10 start
mem[8'h24] = 16'h0000; // 00
mem[8'h25] = 16'h0001; // 01
mem[8'h26] = 16'h0003; // 11 sda 1
mem[8'h27] = 16'h0001; // 01
mem[8'h28] = 16'h0000; // 00
mem[8'h29] = 16'h0002; // 10 sda 10
mem[8'h2A] = 16'h0000; // 00
mem[8'h2B] = 16'h0002; // 10 sda 100
mem[8'h2C] = 16'h0000; // 00
mem[8'h2D] = 16'h0001; // 01
mem[8'h2E] = 16'h0003; // 11 sda 1001
mem[8'h2F] = 16'h0001; // 01
mem[8'h30] = 16'h0000; // 00
mem[8'h31] = 16'h0002; // 10 sda 10010
mem[8'h32] = 16'h0000; // 00
mem[8'h33] = 16'h0001; // 01
mem[8'h34] = 16'h0003; // 11 sda 100101
mem[8'h35] = 16'h0001; // 01
mem[8'h36] = 16'h0003; // 11 sda 1001011 .. 0x4B
mem[8'h37] = 16'h0001; // 01
mem[8'h38] = 16'h0000; // 00
mem[8'h39] = 16'h0002; // 10 send 0 ... write
mem[8'h3A] = 16'h0000; // 00
mem[8'h3B] = 16'h0001; // 01
mem[8'h3C] = 16'h0003; // 11 read ack
mem[8'h3D] = 16'h0001; // 01
mem[8'h3E] = 16'h0000; // 00
mem[8'h3F] = 16'h0002; // 10 write 0
mem[8'h40] = 16'h0000; // 00
mem[8'h41] = 16'h0002; // 10 write 00
mem[8'h42] = 16'h0000; // 00
mem[8'h43] = 16'h0002; // 10 write 000
mem[8'h44] = 16'h0000; // 00
mem[8'h45] = 16'h0002; // 10 write 0000
mem[8'h46] = 16'h0000; // 00
mem[8'h47] = 16'h0002; // 10 write 00000
mem[8'h48] = 16'h0000; // 00
mem[8'h49] = 16'h0002; // 10 write 000000
mem[8'h4A] = 16'h0000; // 00
mem[8'h4B] = 16'h0002; // 10 write 0000000
mem[8'h4C] = 16'h0000; // 00
mem[8'h4D] = 16'h0002; // 10 write 00000000 .... write register 0
mem[8'h4E] = 16'h0000; // 00
mem[8'h4F] = 16'h0001; // 01
mem[8'h50] = 16'h0003; // 11 read ack
mem[8'h51] = 16'h0001; // 01
mem[8'h52] = 16'h0003; // 11
mem[8'h53] = 16'h0002; // 10 ... repeat start
mem[8'h54] = 16'h0000; // 00
mem[8'h55] = 16'h0001; // 01
mem[8'h56] = 16'h0003; // 11 sda 1
mem[8'h57] = 16'h0001; // 01
mem[8'h58] = 16'h0000; // 00
mem[8'h59] = 16'h0002; // 10 sda 10
mem[8'h5A] = 16'h0000; // 00
mem[8'h5B] = 16'h0002; // 10 sda 100
mem[8'h5C] = 16'h0000; // 00
mem[8'h5D] = 16'h0001; // 01
mem[8'h5E] = 16'h0003; // 11 sda 1001
mem[8'h5F] = 16'h0001; // 01
mem[8'h60] = 16'h0000; // 00
mem[8'h61] = 16'h0002; // 10 sda 10010
mem[8'h62] = 16'h0000; // 00
mem[8'h63] = 16'h0001; // 01
mem[8'h64] = 16'h0003; // 11 sda 100101
mem[8'h65] = 16'h0001; // 01
mem[8'h66] = 16'h0003; // 11 sda 1001011 .. 0x4B
mem[8'h67] = 16'h0001; // 01
mem[8'h68] = 16'h0003; // 11 send 1 ... read
mem[8'h69] = 16'h0001; // 01
mem[8'h6A] = 16'h0003; // 11 read ack
mem[8'h6B] = 16'h0001; // 01
mem[8'h6C] = 16'h0003; // 11 read 1st bit
mem[8'h6D] = 16'h0001; // 01
mem[8'h6E] = 16'h0003; // 11 read 2nd bit
mem[8'h6F] = 16'h0001; // 01
mem[8'h70] = 16'h0003; // 11 read 3rd bit
mem[8'h71] = 16'h0001; // 01
mem[8'h72] = 16'h0003; // 11 read 4th bit
mem[8'h73] = 16'h0001; // 01
mem[8'h74] = 16'h0003; // 11 read 5th bit
mem[8'h75] = 16'h0001; // 01
mem[8'h76] = 16'h0003; // 11 read 6th bit
mem[8'h77] = 16'h0001; // 01
mem[8'h78] = 16'h0003; // 11 read 7th bit
mem[8'h79] = 16'h0001; // 01
mem[8'h7A] = 16'h0003; // 11 read 8th bit
mem[8'h7B] = 16'h0001; // 01
mem[8'h7C] = 16'h0000; // 00
mem[8'h7D] = 16'h0002; // 10 write ack
mem[8'h7E] = 16'h0000; // 00
mem[8'h8F] = 16'h0001; // 01
mem[8'h80] = 16'h0003; // 11 read ack
mem[8'h81] = 16'h0001; // 01
mem[8'h82] = 16'h0003; // 11 read 1st bit
mem[8'h83] = 16'h0001; // 01
mem[8'h84] = 16'h0003; // 11 read 2nd bit
mem[8'h85] = 16'h0001; // 01
mem[8'h86] = 16'h0003; // 11 read 3rd bit
mem[8'h87] = 16'h0001; // 01
mem[8'h88] = 16'h0003; // 11 read 4th bit
mem[8'h89] = 16'h0001; // 01
mem[8'h8A] = 16'h0003; // 11 read 5th bit
mem[8'h8B] = 16'h0001; // 01
mem[8'h8C] = 16'h0003; // 11 read 6th bit
mem[8'h8D] = 16'h0001; // 01
mem[8'h8E] = 16'h0003; // 11 read 7th bit
mem[8'h8F] = 16'h0001; // 01
mem[8'h90] = 16'h0003; // 11 read 8th bit
mem[8'h91] = 16'h0001; // 01
mem[8'h92] = 16'h0003; // 11 write NACK
mem[8'h93] = 16'h0001; // 01
mem[8'h94] = 16'h0000; // 00
mem[8'h95] = 16'h0002; // 10
mem[8'h96] = 16'h0003; // 11 stop the transfering
mem[8'h97] = 16'h0001; // 01
end
endmodule
Counter: 2063,
today: 2,
yesterday: 0