# Perancangan Deep Q-Learning Accelerator Pengerjanaan dilakukan secara modular dengan memecah verilog per-sub-sistem dari keseluruhan arsitektur. Rancangan Q-Learning Accelerator yang akan diimplementasikan adalah sebagai berikut. [TOC] :::warning Perancangan ini masih dikerjakan ::: *** ## Pemodelan Sistem Sistem dimodelkan oleh Satrio PL dengan penjelasan sebagai berikut. Bentuk layer yang ada di matlab Okinawa: ![](https://i.imgur.com/tK7wF6A.png) Fungsi fungsi yang dibawah ini berdasarkan yang ada di matlab Okinawa: Parameter awal: - Jumlah episode maks = 10000 - Jumlah step maks = 10 - Lingkungan maze dan reward yang ada - Inisialisasi state awal agen - Jumlah hidden layer awal = 5, aktivasi fungsi sigmoid Persamaan fungsinya: ![](https://i.imgur.com/0aZy8Wx.png) Bentuk grafiknya: ![](https://i.imgur.com/FNDhrvn.png) - Aktivasi fungsi output layer : linear Ya kayak fungsi linear biasa. - Learning param: Alpha : 0.001 Gamma : 0.9 Buat weight dan bias untuk tiap panah pada layer: - w12 : artinya besar suatu nilai dari input ke hidden layer (di inisialisasi awal dengan nilai random (0-1)) - b2 : artinya besar suatu bias dari input layer ke hidden layer (dibuat nilai -1) - w23 : artinya besar suatu nilai dari hidden layer ke output layer (di inisialisasi awal dengan nilai random (0-1)) - b3 : artinya besar suatu bias dari hidden layer ke output (dibuat nilai -1) Proses learning : - inisiasi epsilon - for episode 1 sampe max eps: - st1 = 1 - decrease epsilon - for step = 1 sampe max step: - random data (nilai ini dipake untuk nentuin milih aksi random atau dari nilai Q) - Pake fungsi forward prop (dijelasin dibawah, nama fungsinya sw_move_state), keluaran dari fungs ini : next_state_num, action, Qt(dalam bentuk array 4 index)) - St1= next_state_num, at = action - Ada penalty (dijelasin dibawah) - Peroleh reward dari lingkungan - Update w12, b2, w23, b3 (pake fungsi yang dijelasin dibawah) - Kalo sudah sampe goal, for loop ini berhenti (break) - Kalo sudah learning sampe max episode, learning selesai. Fungsi – fungsi yang dijelaskan diatas: Forward prop : perkalian matriks Simbol input layer I, hidden layer H, output layer O Dari input layer ke hidden layer ![](https://i.imgur.com/MehDL3s.png) Dari hidden layer ke output ![](https://i.imgur.com/TWbPR0Z.png) Update weight and bias Di fungsi update ini pada awalnya pake fungsi forward prop pada next_state yang dipake sebelumnya. Terus ada fungsi back prop : (fungsi ini dipake untuk memperbaharui nilai weight and bias yang ada pada network) intinya di back prop ini ada persamaan derivative. Tapi derivative yang ada gak susah, Cuma perkalian doang. Untuk derivative dari fungsi sigmoid = ![](https://i.imgur.com/aCTUeB4.png) Terus nanti akhirnya Cuma penjumlahan matriks doang. Jadi intinya untuk DQN coba dibuat dulu proses perkalian matriks, penjumlahan matriks, fungsi transpose matriks, dan element wise multiplication matriks. Contoh perkalian matriks yang dipake di forward prop : ![](https://i.imgur.com/SPkgqf3.png) Contoh element wise multip matriks: (dipake untuk derivative di back propagation) ![](https://i.imgur.com/r3aKkZ5.png) ## Perancangan PL (Verilog) ### Matrix Pada Verilog Untuk dapat melakukan operasi matriks maka perlu diketahui deklarasi matriks pada Verilog. Sayangnya, ==Verilog belum mendukung tipe data matriks sebagai port input==. Untuk itu perlu digunakan sedikit modifikasi menggunakan Verilog Generate Blocks dengan Packed Arrays dan Unpacked Arrays. #### Packed Arrays Array jenis ini adalah array yang deklarasi dimensi nya dilakukan sebelum nama objek sehingga seperti Vector. Tipe data yang dapat digunakan hanyalah data 1-bit sehingga merupakan sekumpulan bit yang contiguous. Contoh nya: ``` reg [31:0] temp; // Concatenation (for Initialization) wire [7:0] a = {4'd7, 4'd14}; // Nested Concatenation wire [7:0] b = {{1'b0,1'b1,1'b1,1'b1},{1'b1,1'b1,1'b1,1'b0}}; ``` #### Unpacked Arrays Berbeda dengan packed, jenis ini melakukan deklarasi setelah nama objek. Tipe data yang digunakan dapat berupa apa saja. Contoh nya: ``` reg temp [0:1023]; // Array Assignment integer c [0:3] = '{0, 1, 2, 3}; // Nested Array Assignment integer d [0:3][0:2] = '{'{0,1,2,3},'{4,5,6,7},'{8,9,10,11}}; ``` #### Multi-dimensional Arrays Array ini merupakan gabungan dari packed dan unpacked. Array pada verilog hanya dapat diakses satu data pada satu waktu. Pada array contiguous, maka data dapat diambil per element atau sekelompok elemen satu dimensi yang dinamakan dengan slice. Contoh nya : ``` car B = car A [7:6]; // select a 2-vector slice from car A car B = car A [6+:2]; // equivalent to car A[7:6] // Concatenation and Array Assignment wire [7:0] e [0:3] = '{{4'd7, 4'd14}, 8'd1, {4'd5, 4'd3}, 8'd3}; ``` #### Packed Arrays Assignment Berikut operasi assignment yang dapat dilakukan pada packed arrays. ``` logic [1:0][1:0][7:0] packed_3d_array; always_ff @(posedge clk, negedge rst_n) if (!rst_n) begin packed_3d_array <= '0; // assign 0 to all elements of array end else begin packed_3d_array[0][0][0] <= 1'b0; // assign one bit packed_3d_array[0][0] <= A0a; // assign one element packed_3d_array[0][0][3:0] <= 4'ha; // assign part select packed_3d_array[0] <= 16'habcd; // assign slice packed_3d_array <= 32'h01234567; // assign entire array as vector end `````` #### Unpacked Arrays Assignment Berikut operasi assignment yang dapat dilakukan pada unpacked arrays. ``` logic [7:0] a, b, c; logic [7:0] d_array[0:3]; logic [7:0] e_array[3:0]; // note index of unpacked dimension is reversed logic [7:0] mult_array_a[3:0][3:0]; logic [7:0] mult_array_b[3:0][3:0]; always_ff @(posedge clk, negedge rst_n) if (!rst_n) begin d_array <= '{default:0}; // assign 0 to all elements of array end else begin d_array <= '{A00, c, b, a}; // d_array[0]=A00, d_array[1]=c, d_array[2]=b, d_array[3]=a e_array <= '{A00, c, b, a}; // e_array[3]=A00, e_array[2]=c, e_array[1]=b, d_array[0]=a mult_array_a <= '{'{A00, A01, A02, A03}, '{A04, A05, A06, A07}, '{A08, A09, A0a, A0b}, '{A0c, A0d, A0e, A0f}}; // assign to full array mult_array_b[3] <= '{A00, A01, A02, A03}; // assign to slice of array end `````` #### Packed and Unpacked Arrays Assignment `````` wire [383:0] array = {{0,1,2,3},{4,5,6,7},{8,9,10,11}}; //Valid integer array [0:3][0:2] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}}; //Invalid integer array [0:3][0:2] = '{'{0,1,2,3},'{4,5,6,7},'{8,9,10,11}}; //Valid `````` ### Blok Generate Pada Verilog Memiliki dua buah kegunaan : 1. Untuk menginisiasi modul yang sama secara berulang-kali 2. Melakukan instantinasi kondisional dari sebuah modul Blok ini tidak dapat mengandung port, parameter, specparam, atau specify. Namun modul lainnya diperbolehkan. Semua blok generate terdapat di dalam module dengan keywords generate dan endgenerate. Modul yang dibuat (diinstantinasi) dapat berupa continuos assignments, always / initial blok, dan user defined priimitives. ==Genvar dan Generate hanya merupakan directive yang akan diterjemahkan oleh Synthesizer== sehinga meng-unroll loop menjadi, sebagai contoh : `````` genvar i; generate for(i = 0; i< 2; i = i + 1) begin assign x[i] = i; end endgenerate `````` ekuivalen dengan `````` assign x[0] = 0; assign x[1] = 1; `````` #### Generate "for Loop" `````` module ha (input a,b, output sum,cout); assign sum = a ^ b; assign cout = a&b; endmodule // N instance of half adder module my_design #(parameter N=4) ( input [N-1:0] a, b, output [N-1:0] sum, cout); // Temporary loop variable, won't be seen during // simulation genvar i; // For loop generate for(i = 0; i < N; i = i +1) begin ha u0 (a[i], b[i], sum[i], cout[i]); end endgenerate endmodule `````` #### Testbench untuk Generate "for Loop" `````` module tb; parameter N = 2; reg [N-1:0] a, b; wire [N-1:0] sum, cout; my_design #(.N(N)) md( .a(a), .b(b), .sum(sum), .cout(cout)); initial begin a <= 0; b <= 0; $monitor ("a=0x%0h b=0x%0h sum=0x%0h cout=0x%0h, a, b, sum, cout"); #10 a <= 'h2; b <= 'h3; #20 b <= 'h4; #10 a <= 'h5; end endmodule `````` #### Blok RTL ![](https://i.imgur.com/vr7PfZn.png) #### Contoh lain `````` Example of parameterized gray to binary code converter module gray2bin #(parameter SIZE = 8) ( input [SIZE-1:0] gray, output [SIZE-1:0] bin ) Genvar gi; // generate and endgenerate is optional // generate (optional) for (gi=0; gi&lt;SIZE; gi=gi+1) begin : genbit assign bin[gi] = ^gray[SIZE-1:gi]; // Thanks Dhruvkumar! end // endgenerate (optional) endmodule `````` `````` module addergen1 #(parameter SIZE = 4) ( input logic [SIZE-1:0] a, b, input logic ci, output logic co, output logic [SIZE-1:0] sum ); wire [SIZE :0] c; genvar i; assign c[0] = ci; // Hierarchical gate instance names are: // xor gates: bitnum[0].g1 bitnum[1].g1 bitnum[2].g1 bitnum[3].g1 // bitnum[0].g2 bitnum[1].g2 bitnum[2].g2 bitnum[3].g2 // and gates: bitnum[0].g3 bitnum[1].g3 bitnum[2].g3 bitnum[3].g3 // bitnum[0].g4 bitnum[1].g4 bitnum[2].g4 bitnum[3].g4 // or gates: bitnum[0].g5 bitnum[1].g5 bitnum[2].g5 bitnum[3].g5 // Gate instances are connected with nets named: // bitnum[0].t1 bitnum[1].t1 bitnum[2].t1 bitnum[3].t1 // bitnum[0].t2 bitnum[1].t2 bitnum[2].t2 bitnum[3].t2 // bitnum[0].t3 bitnum[1].t3 bitnum[2].t3 bitnum[3].t3 for(i=0; i&lt;SIZE; i=i+1) begin:bitnum wire t1, t2, t3; xor g1 ( t1, a[i], b[i]); xor g2 ( sum[i], t1, c[i]); and g3 ( t2, a[i], b[i]); and g4 ( t3, t1, c[i]); or g5 ( c[i+1], t2, t3); end assign co = c[SIZE]; endmodule `````` #### Macros Saat menggunakan macros berikut : `````` `define PACK_ARRAY(PK_WIDTH,PK_LEN,PK_SRC,PK_DEST) genvar pk_idx; generate for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) begin; assign PK_DEST[((PK_WIDTH)*pk_idx+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx)] = PK_SRC[pk_idx][((PK_WIDTH)-1):0]; end; endgenerate `define UNPACK_ARRAY(PK_WIDTH,PK_LEN,PK_DEST,PK_SRC) genvar unpk_idx; generate for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin; assign PK_DEST[unpk_idx][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx)]; end; endgenerate module pack_unpack ( input [63:0] pack_4_16_in, output [31:0] pack_16_2_out ); wire [3:0] in [0:15]; `UNPACK_ARRAY(4,16,in,pack_4_16_in) wire [15:0] out [0:1]; `PACK_ARRAY(16,2,in,pack_16_2_out) // useful code goes here endmodule // example `````` Terdapat error karena saat macros diterjemahkan, tedapat semicolon yang tidak seharusnya pada setelah begin (;) dan end (;), sehingga setelah dihapus, warning nya hilang. ==Macros tersebut perlu dirubah karena matrix yang digunakan merupakan array 2 Dimensi==, sehingga dibentuk Macros baru dengan definisi sebagai berikut. `````` `define PACK_ARRAY_2D(PK_WIDTH,PK_LEN,PK_DIMS,PK_SRC,PK_DEST) genvar pk_idx; genvar pk_dims; generate for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) begin for (pk_dims=0; pk_dims<(PK_DIMS); pk_dims=pk_dims+1) begin assign PK_DEST[((PK_WIDTH)*pk_idx*pk_dims+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx*pk_dims)] = PK_SRC[pk_idx][pk_dims][((PK_WIDTH)-1):0]; end end endgenerate `define UNPACK_ARRAY_2D(PK_WIDTH,PK_LEN,PK_DIMS,PK_DEST,PK_SRC) genvar unpk_idx; genvar unpk_dims; generate for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin for (unpk_dims=0; unpk_dims<(PK_DIMS); unpk_dims=unpk_dims+1) begin assign PK_DEST[unpk_idx][unpk_dims][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx*unpk_dims+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx*unpk_dims)]; end end endgenerate `````` ### Blok Transpose Matrix Weight ==Terdapat tiga bagian utama blok ini, pertama adalah unpack array 2D, kemudian mentranspose matriks tersebut, dan mempack kembali sebagai output.== Setelah beberapa kali debugging, didapatkan hasil simulasi telah sesuai. Meski begitu, blok ini kedepannya tidak digunakan karena hanya untuk menguji pack_unpack saja. `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Xirka // Engineer: Adnan // // Create Date: 04/01/2022 13:15:00 AM // Design Name: DQN // Module Name: matrix_weight_transpose // Project Name: DQN // Target Devices: Zybo Zynq-7000 // Tool Versions: 2020.1 // Description: Program Matrix Weight Transpose // // Dependencies: // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // Macros for Matrix `include "pack_unpack.v" module matrix_weight_transpose#(parameter BIT_LGTH = 32, COLM = 9, ROWS = 5, OFFS1 = 4, OFFS2 = 8) ( input signed [(COLM)*(ROWS)*(BIT_LGTH)-1:0] weight, // 5 columns, 9 rows, 32 bit data length output signed [(ROWS)*(COLM)*(BIT_LGTH)-1:0] weight_transposed // 9 columns, 5 rows, 32 bit data length ); wire [(BIT_LGTH-1):0] weight_in [(COLM-1):0][(ROWS-1):0]; `UNPACK_ARRAY_2D(BIT_LGTH,COLM,ROWS,weight_in,weight,OFFS1) wire [(BIT_LGTH-1):0] weight_out [(ROWS-1):0][(COLM-1):0]; `PACK_ARRAY_2D(BIT_LGTH,ROWS,COLM,weight_out,weight_transposed,OFFS2) generate // Computing the transpose genvar i; for (i = 0; i < COLM; i = i + 1) begin : columns genvar j; for (j = 0; j < ROWS; j = j + 1) begin : rows assign weight_out[j][i] = weight_in[i][j]; end end endgenerate endmodule `````` testbench nya : `````` module matrix_weight_transpose_sim(); reg [9*5*32-1:0] in; wire [9*5*32-1:0] out; matrix_weight_transpose MWT(.weight(in), .weight_transposed(out)); initial begin in = {{5{32'hAAAAAAAA}} , {5{32'hBBBBBBBB}} , {5{32'hCCCCCCCC}}, {5{32'hDDDDDDDD}} , {5{32'hEEEEEEEE}}, {5{32'hFFFFFFFF}}, {5{32'hAAAAAAAA}} , {5{32'hBBBBBBBB}} , {5{32'hCCCCCCCC}}} ; #30; end endmodule `````` ### Blok Dot Product Matrix Weight dengan Matrix Input Layer Modul ini masih menggunakan full-pararel multiplier untuk perkalian setiap elemen matrix. Hal tersebut sangat boros area sehingga akan digantikan dengan arsitektur Systolic. `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Xirka // Engineer: Adnan // // Create Date: 04/01/2022 13:15:00 AM // Design Name: DQN // Module Name: matrix_W_dot_I // Project Name: DQN // Target Devices: Zybo Zynq-7000 // Tool Versions: 2020.1 // Description: Program Matrix Weight Dot Product Input Layer // // Dependencies: // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // Macros for Matrix `include "pack_unpack.v" module matrix_w_dot_i#(parameter BIT_LGTH = 32, COLM = 9, ROWS = 5) ( input signed [(COLM)*(ROWS)*(BIT_LGTH)-1:0] weight_TRPS, // Transposed Weight input signed [(COLM)*(BIT_LGTH)-1:0] input_layer, // Input Layer input clk, output signed [(ROWS)*(BIT_LGTH)-1:0] w_dot_i // Weight dot product Input ); wire [(BIT_LGTH-1):0] weight_TRPS_in [(ROWS-1):0][(COLM-1):0]; `UNPACK_ARRAY_2D((BIT_LGTH),(ROWS),(COLM),weight_TRPS_in,weight_TRPS,8) wire [(BIT_LGTH-1):0] input_layer_in [(COLM-1):0]; `UNPACK_ARRAY((BIT_LGTH),(COLM),input_layer_in,input_layer) wire [(BIT_LGTH-1):0] w_dot_i_out [(ROWS-1):0]; `PACK_ARRAY((BIT_LGTH),(ROWS),w_dot_i_out,w_dot_i) reg [(BIT_LGTH-1):0] result [(ROWS-1):0]; generate // Computing the dot product genvar i; for (i = 0; i < (ROWS); i = i + 1) begin : columns genvar j; for (j = 0; j < (COLM); j = j + 1) begin : rows always@(posedge clk) begin if (j==0) result[j] <= weight_TRPS_in[i][j]* input_layer_in[j]; else result[j] <= result[j-1] + weight_TRPS_in[i][j]* input_layer_in[j]; end end assign w_dot_i_out[i] = result[i]; end endgenerate endmodule `````` testbench nya : `````` module matrix_w_dot_i_sim(); reg [9*5*32-1:0] weight_in; reg [9*32-1:0] layer_in; reg clk = 1'b0; wire [9*5*32-1:0] out; matrix_w_dot_i MWDI(.weight_TRPS(weight_in), .input_layer(layer_in), .clk(clk), .w_dot_i(out)); initial begin weight_in = {{9{32'hAAAAAAAA}} , {9{32'hBBBBBBBB}} , {9{32'hCCCCCCCC}}, {9{32'hDDDDDDDD}} , {9{32'hEEEEEEEE}}} ; layer_in = {{{32'hAAAAAAAA}} , {{32'hBBBBBBBB}} , {{32'hCCCCCCCC}} , {{32'hDDDDDDDD}} , {{32'hEEEEEEEE}} , {{32'hFFFFFFFF}} , {{32'hAAAAAAAA}} , {{32'hBBBBBBBB}} , {5{32'hCCCCCCCC}}} ; #30; end always begin clk = ~clk; #10; end endmodule `````` ### Blok Penjumlahan Matrix dari Input Layer ke Hidden Layer `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Xirka // Engineer: Adnan // // Create Date: 04/01/2022 13:15:00 AM // Design Name: DQN // Module Name: matrix_addition_IH // Project Name: DQN // Target Devices: Zybo Zynq-7000 // Tool Versions: 2020.1 // Description: Program Matrix Addition from Input Layer to Hidden Layer // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // Macros for Matrix `include "pack_unpack.v" module matrix_addition_IH #(parameter BIT_LGTH = 32, COLM = 1, ROWS = 5) ( input signed [(ROWS)*(BIT_LGTH)-1:0] w_dot_i, // 5 rows input signed [(ROWS)*(BIT_LGTH)-1:0] bias, // 5 rows input clk, output signed [(ROWS)*(BIT_LGTH)-1:0] IH // 5 rows ); wire [31:0] w_dot_i_in [4:0]; `UNPACK_ARRAY((BIT_LGTH),(ROWS),w_dot_i_in,w_dot_i) wire [31:0] bias_in [4:0]; `UNPACK_ARRAY2((BIT_LGTH),(ROWS),bias_in,bias) wire [31:0] IH_out [4:0]; `PACK_ARRAY((BIT_LGTH),(ROWS),IH_out,IH) generate // Computing the matrix addition genvar i; for (i = 0; i < (ROWS); i = i + 1) begin : rows assign IH_out[i] = w_dot_i_in[i] + bias_in[i]; end endgenerate endmodule `````` testbench nya: `````` module matrix_addition_IH_sim #(parameter BIT_LGTH = 32, COLM = 1, ROWS = 5)(); reg [(ROWS)*(BIT_LGTH)-1:0] w_dot_i_in; reg [(ROWS)*(BIT_LGTH)-1:0] bias_in; reg clk = 1'b0; wire [(ROWS)*(BIT_LGTH)-1:0] IH_out; matrix_addition_IH MAIH(.w_dot_i(w_dot_i_in), .bias(bias_in), .clk(clk), .IH(IH_out)); initial begin w_dot_i_in = {{32'hAAAAAAAA} , {32'hBBBBBBBB} , {32'hCCCCCCCC}, {32'hDDDDDDDD} , {32'hEEEEEEEE}} ; bias_in = {{32'hEEEEEEEE} , {32'hDDDDDDDD} , {32'hCCCCCCCC}, {32'hBBBBBBBB} , {32'hAAAAAAAA}} ; #30; end always begin clk = ~clk; #10; end endmodule `````` ### Blok Activation Function (Sigmoid) Modul ini dibuat menggunakan aproksimasi dari fungsi sigmoid dengan gradien 1/4 dan 1/8 yang ditunjukan dalam bentuk grafik : ![](https://i.imgur.com/K2xdLPW.png) Arsitektur yang digunakan adalah sebagai berikut. ![](https://i.imgur.com/DppiW44.png) `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Xirka // Engineer: Adnan // // Create Date: 04/01/2022 13:15:00 AM // Design Name: DQN // Module Name: matrix_sigmoid // Project Name: DQN // Target Devices: Zybo Zynq-7000 // Tool Versions: 2020.1 // Description: Program Sigmoid Function // // Dependencies: // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // Macros for Matrix `include "pack_unpack.v" module matrix_sigmoid#(parameter BIT_LGTH = 16, COLM = 1, ROWS = 5) ( input signed [(ROWS)*(BIT_LGTH)-1:0] IH, // Weight dot Input(1) input signed [(ROWS)*(BIT_LGTH)-1:0] bias, // Bias 2 => Input to Hidden Layer input clk, output [(ROWS)*(BIT_LGTH)-1:0] IH_sigmoid // Weight dot product Input ); wire [(BIT_LGTH-1):0] IH_in [(ROWS-1):0]; `UNPACK_ARRAY((BIT_LGTH),(ROWS),IH_in,IH) wire [(BIT_LGTH-1):0] bias_in [(ROWS-1):0]; `UNPACK_ARRAY2((BIT_LGTH),(ROWS),bias_in,bias) wire [(BIT_LGTH-1):0] IH_sigmoid_out [(ROWS-1):0]; `PACK_ARRAY((BIT_LGTH),(ROWS),IH_sigmoid_out,IH_sigmoid) wire [(BIT_LGTH-1):0] IH_in_temp [(ROWS-1):0]; generate // Computing the sigmoid function genvar i; for (i = 0; i < (ROWS); i = i + 1) begin : rows assign IH_in_temp[i] = IH_in[i] + bias_in[i]; sigmoid #(.BIT_LGTH(BIT_LGTH)) a0 (.in(IH_in_temp[i]), .out(IH_sigmoid_out[i])); end endgenerate endmodule module sigmoid#(parameter BIT_LGTH = 16)( //input : signed fractional 4 decimal, 20 fractional input signed [(BIT_LGTH-1):0] in, //output : unsigned fractional 0 decimal, 15 fractional output signed [(BIT_LGTH-1):0] out ); localparam signed border1 = 16'hFC00; localparam signed border2 = 16'h0400; localparam signed border3 = 16'hF400; localparam signed border4 = 16'h0C00; wire temp1, temp2, temp3, temp4; wire signed [15:0] outmux0, outmux1, outmux2, outmux3; wire signed [15:0] result; wire signed [15:0] inshift2 = in >>> 3; wire signed [15:0] inshift1 = in >>> 2; wire slc0, slc1, slc4; //slc2=slc1 ; slc3 = slc4 //Temporary wire for signed arithmetic assign temp1 = (in < border1); // Less than -1 assign temp2 = (in >= border2); // More than 1 assign temp3 = (in < border3); // Less than -3 assign temp4 = (in >= border4); // More than 3 //Select wire assignment assign slc0 = in[15]; // slc0 : 1 if negative assign slc1 = temp1 || temp2; // slc1 = (in<-1.0)||(in>1.0) assign slc4 = temp3 || temp4; // slc4 = (in<-3.0)||(in>3.0) //Linear region assign outmux0 = slc0 ? 16'h180 : 16'h0280; //mux0 : Constant selector y1 = 0.375 or y3 = 0.625 assign outmux1 = slc1 ? outmux0 : 16'h0200; //mux1 : Constant selector outmux1 = c (outmux0 or 0.5) assign outmux2 = slc1 ? inshift2 : inshift1; //mux2 : Gradien selector mx (x/8) or (x/4) assign result = outmux2 + outmux1; //adder to calculate output function mx + c //Saturation assign outmux3 = slc0 ? 16'h0000 : 16'h03FF; //mux3 : Saturation selector (0 or 0.999(approximately 1)) //Output assign out = slc4 ? outmux3 : result; endmodule `````` testbench nya: `````` module matrix_sigmoid_sim#(parameter BIT_LGTH = 16, COLM = 1, ROWS = 5)(); reg [(ROWS)*(BIT_LGTH)-1:0] IH_in; reg [(ROWS)*(BIT_LGTH)-1:0] bias_in; reg clk = 1'b0; wire [(ROWS)*(BIT_LGTH)-1:0] IH_sigmoid_out; matrix_sigmoid MS(.IH(IH_in), .bias(bias_in), .clk(clk), .IH_sigmoid(IH_sigmoid_out)); initial begin IH_in = {{16'hF400} , {16'hF800} , {16'h0400}, {16'h1000} , {16'h2000}} ; bias_in = {{16'hFC00} , {16'hFC00} , {16'hFC00}, {16'hFC00} , {16'hFC00}} ; #30; IH_in = {{16'hF500} , {16'hF900} , {16'h0500}, {16'h0BFF} , {16'h2800}} ; end always begin clk = ~clk; #10; end endmodule `````` ### Blok Maximum Q-Value Modul ini akan memilih antara 4 pilihan Action yang dapat diambil dengan mempertimbangkan action mana yang memiliki nilai Q-Value paling maksimum. Arsitektur yang digunakan adalah binary-tree-comparators sebagai gambar berikut. ![](https://i.imgur.com/gZet3Ge.png) `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Xirka // Engineer: Adnan // // Create Date: 10/13/2021 13:15:00 AM // Design Name: DQN // Module Name: MAX // Project Name: DQN // Target Devices: Zybo Zynq-7000 // Tool Versions: 2020.1 // Description: Comparation for Maximum Q value // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module MAX#(parameter BIT_LGTH = 16)( input signed [(BIT_LGTH-1):0] Q_next_state_1, input signed [(BIT_LGTH-1):0] Q_next_state_2, input signed [(BIT_LGTH-1):0] Q_next_state_3, input signed [(BIT_LGTH-1):0] Q_next_state_4, output reg signed [(BIT_LGTH-1):0] Qmax ); reg [(BIT_LGTH-1):0] maximum_1_and_2; reg [(BIT_LGTH-1):0] maximum_3_and_4; always @(Q_next_state_1 or Q_next_state_2) begin if (Q_next_state_1 > Q_next_state_2) maximum_1_and_2 = Q_next_state_1; else maximum_1_and_2 = Q_next_state_2; end always @(Q_next_state_3 or Q_next_state_4) begin if (Q_next_state_3 > Q_next_state_4) maximum_3_and_4 = Q_next_state_3; else maximum_3_and_4 = Q_next_state_4; end wire [(BIT_LGTH-1):0] difference = maximum_1_and_2 - maximum_3_and_4; always @(difference) begin if (difference[(BIT_LGTH-1)] == 0) Qmax = maximum_1_and_2; else Qmax = maximum_3_and_4; end endmodule `````` test bench : `````` module MAX_sim#(parameter BIT_LGTH = 16)(); reg [(BIT_LGTH-1):0] Q_next_state_1_in; reg [(BIT_LGTH-1):0] Q_next_state_2_in; reg [(BIT_LGTH-1):0] Q_next_state_3_in; reg [(BIT_LGTH-1):0] Q_next_state_4_in; wire [(BIT_LGTH-1):0] Qmax_out; MAX MX( .Q_next_state_1(Q_next_state_1_in), .Q_next_state_2(Q_next_state_2_in), .Q_next_state_3(Q_next_state_3_in), .Q_next_state_4(Q_next_state_4_in), .Qmax(Qmax_out)); initial begin #20 Q_next_state_1_in = {16'h10F0}; Q_next_state_2_in = {16'h100F}; Q_next_state_3_in = {16'hF400}; Q_next_state_4_in = {16'h0400}; end endmodule `````` ### Blok Step Counter dan Episode Counter Modul ini akan mengakumulasi setiap kalo satu step selesai diambil (dalam waktu 15 clock). Setiap jumlah step terakumulasi mencapai batas tertentu (maximum step) atau menemukan goal (reward positif) maka episode counter akan bertambah. Terakhir, saat episode counter mencapai jumlah maksimal episode yang diinginkan, learning telah selesai. ==Dua hal== yang perlu diperhatikan adalah ==pertama== bahwa karena format representasi angka yang digunakan adalah Q6.10 maka untuk persamaan dengan jumlah episode perlu direpresentasikan dalam heksa yang bersesuaian. ==Kedua==, karena modul step counter akan menghitung setiap satu step selesai diambil, maka dari itu trigger untuk menambah nilai step counter bukan berasal berasal dari clock melainkan dari Control Unit yang memberitahu bahwa telah sampai pada state selesai satu step. S untuk Episode counter.l step_done dari step counter ataipun dari modul reward. `````` `````` Pada simulasi terdapat sedikit anomali yaitu setelah jumlah maksimum episode sampai, siklus berikutnya menghitung dari state 1 dan loncat ke state 3 tanpa melalui state 2. testbench nya : `````` `````` ### Blok Derivatif C terhadap Action 3 (Bagian 1) Modul ini menghitung sesuai fungsi berikut. Apabila maxQ bernilai kurang dari nol, maka operasi aritmatik akan salah. Namun karena nilai maxQ terbatas antara 0<maxQ<1 maka hal tersebut tidak akan terjadi. ![](https://i.imgur.com/BRfdcyQ.png) `````` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 01/26/2022 03:22:12 AM // Design Name: // Module Name: dC3da // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// // Macros for Matrix `include "pack_unpack.v" module back_addrightmulti_dC3da#(parameter BIT_LGTH = 16, COLM = 1, ROWS = 4, DISC_FCT = 8) ( input signed [(ROWS)*(BIT_LGTH)-1:0] maxQ, input signed [(BIT_LGTH)-1:0] dCdatemp, // Input Layer input [1:0] action, input clk, output signed [(BIT_LGTH)-1:0] dCda // Weight dot product Input ); wire [(BIT_LGTH-1):0] maxQ_in [(ROWS-1):0]; `UNPACK_ARRAY((BIT_LGTH),(ROWS),maxQ_in,maxQ) reg [(BIT_LGTH-1):0] result; generate // Calculating genvar i; for (i = 0; i < (ROWS); i = i + 1) begin : rows always@(posedge clk) begin if (i == action) result <= dCdatemp + (maxQ_in[i] >>> DISC_FCT); end assign dCda = result; end endgenerate endmodule `````` testbench `````` module back_addrightmulti_dC3da_sim(); reg [4*16-1:0] maxQ_in; reg [16-1:0] dc_in; reg [1:0] act_in; reg [3:0] gamma_in; reg clk = 1'b0; wire [16-1:0] out; back_addrightmulti_dC3da BAD (.maxQ(maxQ_in), .dCdatemp(dc_in), .action(act_in), .clk(clk), .dCda(out)); initial begin maxQ_in = {{16'h0F00} , {16'h0FF0}, {16'h0F0F} , {16'h00FF}} ; gamma_in = 4'b1000; act_in = 2'b10; dc_in = 16'hFF00; end always begin clk = ~clk; #1; end endmodule `````` ## Simulasi ### Simulasi Blok Transpose Matrix Weight Model program serupa telah dibuat pada bahasa C dan telah jalan dengan baik. dari ![](https://i.imgur.com/KMPePu9.png) sampai dengan![](https://i.imgur.com/qZMiTIU.png) Namun hasil pada Verilog belum benar karena unpacking dan packing binary masih memiliki kesalahan pada akses array. ![](https://i.imgur.com/YlkPEwg.png) *Matriks 5x9 (bawah) ditranspose menjadi 9x5 (atas)* Setelah debugging yang cukup panjang didapatkan hasil yang sesuai. Input sepanjang 1440 bit diolah kedalam bentuk matriks 9x5, kemudian ditransposes menjadi 5x9, dan di keluarkan sebagai output 1440 bit dengan bentuk matriks yang baru. ![](https://i.imgur.com/yiRML4I.png) *Matriks 9x5 (bawah) ditranspose menjadi 5x9 (atas)* ### Simulasi Blok Dot Product Matrix Weight dengan Matrix Input Layer Triger masih dilakukan melalui clock karena apabila auto sensitivity list, hasil tepat namun tidak muncul bentuk sinyal. ![](https://i.imgur.com/uBOJ6Ts.png) *Matriks Weight (.) Input Layer, hasil pada sinyal paling atas* ### Simulasi Blok Penjumlahan Matrix dari Input Layer ke Hidden Layer ![](https://i.imgur.com/tBvdmt8.png) *Matriks W (.) I + IL, hasil pada sinyal paling bawah* ### Simulasi Blok Activation Function ![](https://i.imgur.com/EPsVqNB.png) *sinyal IH_in_temp merupakan input yang telah dijumlahkan dengan bias, sedangkan IH_sigmoid_out hasil activation function nya* ### Simulasi Blok Maximum Value ![](https://i.imgur.com/LGCjwsO.png) *Empat sinyal masukan dapat dipilih dengan baik mana nilai maksimum nya* ### Simulasi Blok Derivatif C terhadap Action 3 ![](https://i.imgur.com/GdJYCgb.png) *Sinyal keluaran merupakan aproksimasi yang baik dari operasi yang dilakukan* Sinyal akhir : ![](https://i.imgur.com/dMhBbBs.png) ## FAQ #### Q : Simulasi Jalan, hasil keluar tapi waveform tidak muncul #### A : Restart Simulator / Re-open Project #### Q : Multiplication salah, kenapa ? #### A : COBA KASIH SIGNED ! #### Q : Multiplication salah, kenapa ? #### A : Jangan lupa ( ) karena bisa jadi dia <<< dulu baru +