Menu

Concatenation dan Replikasi di Verilog: Operator {}

Cara menyambung sinyal dengan {} dan menyalin sebuah pola N kali dengan {N{...}}, dua operator Verilog yang wajib dikuasai untuk membangun bus yang lebih lebar dari potongan-potongan.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Dua Operator Kecil yang Sangat Berguna

Verilog punya dua bentuk {}:

  1. Concatenation: {a, b, c} menyambung beberapa sinyal menjadi satu sinyal yang lebih lebar.
  2. Replikasi: {N{pattern}} menyalin sebuah pola sebanyak N kali.

Kamu akan terus memakai keduanya. Setiap kali sebuah bus perlu dipecah, disatukan, diberi padding, atau di-sign-extend, salah satu dari dua operator inilah jawabannya.

Concatenation: {a, b, c}

Kasus paling sederhana: menumpuk dua sinyal menjadi satu:

Dibaca dari kiri ke kanan: a adalah separuh atas, b separuh bawah. Operand pertama di dalam {} adalah yang paling signifikan. Lebar hasilnya adalah jumlah lebar semua operand.

Kamu bisa menyambung operand sebanyak apa pun:

wire [31:0] word = {byte3, byte2, byte1, byte0};

Dan lebar operand-nya boleh berbeda-beda:

wire [11:0] frame = {start_bit, data_byte, parity, stop_bit};
//                    1 bit      8 bits     1 bit   2 bits  = 12

Aturan yang umum: semua operand concatenation harus punya lebar yang eksplisit. Literal tanpa ukuran (1 alih-alih 1'b1) menyebabkan error karena parser tidak tahu berapa banyak bit yang harus dialokasikan. Selalu tulis 1'b0, 1'b1, 4'd0, jangan pernah 0 atau 1 begitu saja di dalam {}.

Concatenation di Sisi Kiri

Concatenation di sisi kiri (LHS) penugasan memecah sinyal lebar kembali menjadi bagian-bagiannya:

Itulah pola baku adder dengan carry. {carry_out, sum_bits} adalah satu tujuan 9-bit di sisi kiri penugasan, dan bit-bitnya dibagikan: bit teratas ke carry_out, 8 bit bawah ke sum_bits.

Concatenation di LHS bisa dipakai di assign maupun di blok prosedural:

always @(posedge clk) begin
    {high_byte, low_byte} <= incoming_word;
end

Replikasi: {N{pattern}}

Operator replikasi menyalin sebuah pola sebanyak jumlah yang tetap. Bentuknya {N{pattern}}: jumlahnya, lalu polanya di dalam pasangan kurung kurawal tersendiri:

N harus berupa konstanta, karena compiler perlu tahu lebar hasilnya saat elaborasi. Polanya bisa berupa literal, parameter, atau ekspresi apa pun yang lebarnya diketahui.

Jangan lupa kurung kurawal bagian dalam. {8 1'b1} adalah syntax error; {8{1'b1}} yang benar. {} bagian luar adalah operatornya; {...} bagian dalam membungkus pola yang direplikasi.

Menggabungkan Keduanya: Sign Extension dan Zero Extension

Kedua operator ini bisa digabungkan dengan alami untuk membangun nilai yang lebih lebar:

{ {8{a_negative[7]}}, a_negative } adalah pola sign extension yang standar. Bacalah begini: replikasi bit tanda delapan kali, lalu sambungkan 8 bit aslinya. Hasil akhirnya: representasi two's complement 16-bit dari angka yang sama.

Untuk pelebaran unsigned, kamu bisa mengandalkan penugasan, karena Verilog otomatis melakukan zero-extend saat tujuannya lebih lebar:

wire [15:0] zext_auto = a_unsigned;   // works, top 8 bits are 0

Tapi sign extension tidak pernah terjadi secara implisit kecuali operand dan tujuannya sama-sama dideklarasikan signed. Idiom replikasi yang eksplisit lebih aman.

Pola yang Berguna

Membangun Mask Berisi N Angka Satu

parameter N = 5;
wire [31:0] mask = { {32-N{1'b0}}, {N{1'b1}} };
// e.g. with N=5, mask = 32'h0000_001F

Membalik Urutan Vektor

Verilog tidak punya fungsi reverse bawaan, tapi kamu bisa menulisnya langsung dengan concatenation:

wire [3:0] forward  = 4'b1010;
wire [3:0] reversed = {forward[0], forward[1], forward[2], forward[3]};
// reversed = 4'b0101

Untuk vektor yang lebih lebar, loop generate atau sebuah function lebih rapi.

Mengemas Flag ke Byte Status

wire [7:0] status = {
    error_flag,    // [7]
    overflow,      // [6]
    underflow,     // [5]
    ready,         // [4]
    busy,          // [3]
    1'b0,          // [2] reserved
    1'b0,          // [1] reserved
    valid          // [0]
};

Slot cadangan 1-bit itu punya lebar yang eksplisit: jangan pernah 0 begitu saja di dalam {}.

Kesalahan yang Umum

Literal tanpa ukuran di dalam {}. {a, 0} adalah syntax error atau nol selebar 32 bit. Selalu beri ukuran: {a, 1'b0}.

Lupa kurung kurawal dalam di replikasi. {8 1'b1} tidak bisa di-parse; {8{1'b1}} bisa.

Tertukar urutannya. {a, b} menaruh a di sisi atas dan b di sisi bawah. Kalau anggapanmu terbalik, urutan byte-mu akan terbalik di suatu tempat.

Mereplikasi nol kali. {0{...}} tidak sah di Verilog standar. SystemVerilog mengizinkannya (dan menghasilkan hasil selebar nol). Verilog biasa akan menolaknya.

Selanjutnya

Sekarang kamu sudah melihat setiap operator Verilog. Bab berikutnya berganti arah dan masuk ke struktur: bagaimana module saling terhubung, aturan port, dan sintaks untuk membuat instance sub-module guna membangun desain yang lebih besar.

Pertanyaan yang sering diajukan

Bagaimana cara menggabungkan sinyal di Verilog?

Pakai kurung kurawal: {a, b, c} menghasilkan satu vektor lebar dengan menyambung operand-operand-nya dari kiri ke kanan. MSB dari a menjadi MSB hasilnya; LSB dari c menjadi LSB-nya. Lebar hasilnya adalah jumlah lebar semua operand. Concatenation bisa dipakai di sisi kanan penugasan (untuk membangun nilai) maupun di sisi kiri (untuk memecah nilai).

Apa arti {N{pattern}} di Verilog?

Itu operator replikasi: ia menghasilkan N salinan pattern yang disambung menjadi satu. {8{1'b1}} adalah nilai 8-bit yang semuanya satu (8'hFF). {4{2'b10}} adalah nilai 8-bit 8'b10101010. Replikasi adalah cara melakukan zero-extend, sign-extend, atau membangun pola bit berulang apa pun tanpa menuliskannya satu per satu.

Bagaimana cara melakukan sign-extend pada sinyal di Verilog?

Pakai replikasi untuk mengulang bit tanda: { {24{a[7]}}, a } memperluas a yang 8-bit menjadi 32 bit dengan mereplikasi bit 7 (bit tanda) sebanyak 24 kali lalu menyambungkan nilai aslinya. Untuk zero-extend unsigned, replikasi 1'b0 atau biarkan penugasan melakukannya secara implisit saat tujuannya lebih lebar.

Bisakah concatenation dipakai di sisi kiri penugasan?

Bisa, dan begitulah cara memberi nilai ke beberapa target dari satu sumber yang lebar. {carry, sum} = a + b; menaruh hasil penjumlahan ke carry (bit teratas) dan sum (sisanya) dalam satu pernyataan. Setiap target tetap dengan lebarnya; parser membagikan bit-bit dari sisi kanan sesuai lebar itu.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai