Skip to content
DevBJ
Go back

SystemVerilog 배열을 flat bus로 묶고 byte slice 선택하기

Updated:
Editor

고정 폭 flat bus에 배열 원소를 연결할 때는 각 원소의 시작 bit와 폭을 정해 매핑한다. SystemVerilog의 indexed part-select인 +:는 기준 bit부터 지정한 폭만큼 bit를 선택한다.

byte 단위 slice

내림차순으로 선언한 logic [31:0] data에서 네 byte를 나누려면 다음과 같이 쓸 수 있다.

logic [31:0] data;
logic [7:0] byte0, byte1, byte2, byte3;

always_comb begin
  byte0 = data[0 +: 8];  // data[7:0]
  byte1 = data[8 +: 8];  // data[15:8]
  byte2 = data[16 +: 8]; // data[23:16]
  byte3 = data[24 +: 8]; // data[31:24]
end

[base +: width]에서 두 번째 값은 끝 index가 아니라 선택할 bit 수다. 반대 방향으로 선택하려면 -:를 사용한다. 예제의 결과는 packed vector가 [31:0]으로 선언된 경우다.

배열을 flat bus로 묶기

배열 원소마다 bus의 연속된 WIDTH bit를 연결하면 된다.

module pack_bytes #(
  parameter int unsigned COUNT = 4,
  parameter int unsigned WIDTH = 8
) (
  input  logic [WIDTH-1:0] bytes [0:COUNT-1],
  output wire [COUNT*WIDTH-1:0] flat
);
  for (genvar i = 0; i < COUNT; i++) begin : gen_pack
    assign flat[i*WIDTH +: WIDTH] = bytes[i];
  end
endmodule

이 예제는 SystemVerilog의 unpacked array port를 사용한다. Verilog만 지원하는 경계나 외부 interface에는 flat vector를 port로 두고, 모듈 내부에서 같은 indexed part-select 규칙으로 원소를 풀어 쓴다.

bit 순서를 고정하기

위 mapping은 bytes[0]을 flat[WIDTH-1:0]에 둔다. 반대로 가장 높은 slice부터 첫 원소를 놓고 싶다면 mapping 식을 바꿔야 한다. 송신 측과 수신 측이 같은 byte 순서와 bit 순서를 사용하는지 interface 문서에 적는다.

확인 순서

  1. 배열 원소 수와 각 원소의 폭을 확인한다.
  2. flat vector 폭이 COUNT × WIDTH인지 확인한다.
  3. 원소 0과 마지막 원소가 의도한 slice에 연결됐는지 확인한다.
  4. simulator와 synthesis tool에서 사용하는 SystemVerilog 문법을 지원하는지 확인한다.

공식 자료

원문 기록

한 줄 요약

배열과 flat bus를 변환할 때는 원소 폭, 시작 bit, byte 순서를 명시하고 indexed part-select의 두 번째 값은 bit 폭으로 쓴다.


Share this post on:

Previous Post
WaveDrom으로 clock과 bus timing diagram 그리기
Next Post
SystemVerilog package를 공유할 때 compile order 확인하기