-
[SystemVerilog] 인터페이스 1개발/SystemVerilog 2022. 1. 16. 18:13
시스템베릴로그에서 디자인, 검증에 쓰이는 문법중에 인터페이스가 가장 유용한거같다.
인터페이스란 아주 간단히 말하면 신호들의 집합이다.
https://www.chipverify.com/systemverilog/systemverilog-interface-intro DUT의 input , output port를 연결하는 신호들 하나로 묶은 것 이상으로 많은 기능을 제공한다.
인터페이스는 모듈처럼 정의할 수 있다.
interface .. endinterface 키워드로 선언한다.
아주 단순한 인터페이스는 신호들을 묶어주는 역할만 하지만,
복잡한 인터페이스는 버스를 모델링 할 수 있고 내부에 태스크를 선언하여 트랜잭션을 만들수도 있다.
다음과 같이 메모리와 cpu를 연결하는 디자인이 있다고 하자.
베릴로그에서는 각각 연결되는 신호들을 모두 정의하고 일일이 포트에 적어주어야 한다.
간단한 모듈이면 코딩작업이 빠르게 되겠지만 모듈의 입출력 신호가 많다면 그것들을 다 적기엔 시간이 오래걸린다.
게다가 실수가 나올 가능성도 커진다.
시스템베릴로그에선 인터페이스를 선언하고 내부에서 입출력 신호를 선언하고 각각의 방향을 정해줄 수 있다.
그리고 모듈 포트에 인터페이스를 인스턴스 하면 간단하게 포트연결을 할 수 있다.
디자인의 유지보수 측면에서 매우 편리하다.
위의 예시를 갖고 인터페이스를 모델링 해보자
module memModule( input logic clk, input logic req, input logic start, input logic [1:0] mode, input logic [7:0] addr, inout wire [7:0] data, output logic gnt, output logic rdy ); endmodule module cpuModule( input logic clk, input logic gnt, input logic rdy, inout wire [7:0] data, output logic req, output logic start, input logic [1:0] mode, input logic [7:0] addr ); endmodule module top(); logic req, gnt, start, rdy; logic clk = 0; logic [1:0] mode; logic [7:0] addr, data; memModule mem(clk, req, start, mode, addr, data, gnt, rdy); cpuModule cpu(clk, gnt, rdy, data, req, start, mode, addr); endmodule
인터페이스를 사용하여 위의 코드를 간략하게 만들것이다.
interface simple_bus(); logic req, start, gnt, rdy; logic [1:0] mode; logic [7:0] addr; wire [7:0] data; endinterface module memModule( input logic clk, simple_bus bus ); endmodule module cpuModule( input logic clk, simple_bus bus ); endmodule module top(); logic clk = 0; simple_bus busA(); // bus declaration memModule mem(clk, busA); cpuModule cpu(clk, busA); endmodule
맨 위에 인터페이스 블록으로 신호들을 선언하고나서 top 모듈 내부에 인터페이스를 인스턴스한다.
그리고 각 모듈에 연결해주면 된다. 인터페이스를 사용하여 기존의 코드를 간략하고 추상화했다.
하지만 위의 인터페이스는 그냥 예시로 만든것이고, 아직 각 모듈에서 신호들의 방향을 설정하지 않았다.
참고로 인터페이스로 선언된 포트도 port mapping rule 적용된다.
module top; logic clk = 0; simple_bus bus; // positional memModule mem(clk, bus); // named memModule mem(.clk(clk), .bus(bus)); // implicit memModule mem(.clk, .bus); memModule mem(.*); endmodule
위의 예제는 사용자가 인터페이스 블럭을 정의하여 모듈 포트에 해당 인터페이스 타입으로 선언을 했다.
모듈 포트에는 유저가 정의한 타입이 아니라 더 범용적인 인터페이스를 정의할 수 있다.
interface simple_bus(); logic req, start, gnt, rdy; logic [1:0] mode; logic [7:0] addr; wire [7:0] data; endinterface module memModule(interface bus_port); ... endmodule module top; simple_bus bus; memModule mem(.bus_port(bus)); endmodule
구조체 멤버변수에 접근하는것 처럼 인터페이스에 정의된 변수들을 참조할 수 있다.
// reference through port name module memModule(input logic clk, simple_bus bus); reg [31:0] mem [0:31]; wire read, write; assign read = bus.gnt && (bus.mode == 0); assign write = bus.gnt && (bus.mode == 1); always @ (posedge clk) begin if (read) bus.data <= mem[bus.addr]; else if (write) mem[bus.addr] <= bus.data; end endmodule // reference through instance module top; logic clk = 0; simple_bus bus; memModule mem(clk, bus); cpuModule cpu(clk, bus); always @(bus.clk) begin if (bus.mode == 0) ... end endmodule
인터페이스 블럭은 모듈처럼 port를 갖을 수 있다.
위의 예제에서 clk을 인터페이스의 입력신호로 정의하면 다음과 같다.
interface simple_bus(input clk); logic req, start, gnt, rdy; logic [1:0] mode; logic [7:0] addr; wire [7:0] data; endinterface module top(); logic clk; simple_bus bus(clk); memModule mem(bus); cpuModule cpu(bus); ... endmodule
clk 신호까지 인터페이스에 포함되므로 memModule, cpuModule의 포트에는 clk 선언을 넣을 필요가 없이 인터페이스만 선언해주면 된다.
'개발 > SystemVerilog' 카테고리의 다른 글
[SystemVerilog] 데이터 타입 5 string (0) 2022.01.17 [SystemVerilog] 인터페이스 2 (0) 2022.01.16 [SystemVerilog] packed / unpacked array (0) 2022.01.15 [SystemVerilog] 데이터 타입 4 struct (0) 2022.01.15 [SystemVerilog] 데이터 타입 3 enum (0) 2022.01.15