2014-12-16 2 views
2

Verilog (중요한 것은 SystemVerilog가 아님)로 작성된 프로젝트가 있습니다.이 프로젝트는 설계의 서로 다른 부분간에 전달되는 신호의 수 때문에 관리하기가 힘들었습니다. . 동일한 신호가 필요한 모듈이 여러 개 있기 때문에 더 적은 수의 명명 된 객체로 모듈을 통합하려고합니다. 질문은 그것을하는 방법입니다.Verilog에서 C struct와 같은 것을 정의 할 수있는 방법이 있습니까?

module mymodule(sig_a_in, sig_b_in, sig_c_in, sig_d_in, sig_e_in, 
       sig_a_out, sig_b_out, sig_c_out, sig_d_out, sig_e_out); 

    input wire sig_a_in, sig_b_in, sig_c_in; 
    input wire [5 : 0] sig_d_in; 
    input wire [31 : 0] sig_e_in; 
    output reg sig_a_out, sig_b_out, sig_c_out; 
    output reg [5 : 0] sig_d_out; 
    output reg [31 : 0] sig_e_out; 
endmodule 

그것은 내가 이름으로 신호를 참조 할 수 가독성을 위해, 내 의견으로는, 중요하다

은의이 내 인위적인 예입니다 가정 해 봅시다. 그러나 각 모듈에 모두 개별적으로 전달하고 싶지는 않습니다. 다시 말하지만,이 프로젝트에서는 Verilog 만 사용하므로 SystemVerilog 구조는 불가능합니다.

첫 번째 생각은 하나의 버스로 결합한 다음 정의 된 이름을 사용하여 개별 와이어를 참조하는 것입니다. 그러나 이것은 특히 다른 버스를 믹스에 추가 할 때 다소 복잡합니다. 신호가 명백한 암시 적 순서를 가지기 때문에 이것은 내 인위적인 예제에서는 꽤 사소한 것이지만 실제로는 그렇지 않습니다. 공구 쇄 구조체에서 와이어의 모듈에 의해 사용되는 것으로 만 와이어를 합성 할 수있는 구별 할 수 있도록

`define SIGNAL_BUS_WIDTH 41 
`define A 0 
`define B 1 
`define C 2 
`define D 3 
`define E 9 

module mymodule(signal_bus_in, signal_bus_out); 

    input wire [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_in; 
    output reg [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_out; 

    // reference a 
    signal_bus_in[`A] 
    // reference d? Not good when names don't have an obvious order 
    signal_bus_in[`E-1 : `D] 
endmodule 

마지막으로,이 모든 이외에 필요가있다. 모든 모듈이 모든 와이어를 사용하는 것은 아니므로 사용하지 않는 여분의 경로가 필요 없습니다. 위의 버스 예에서도 도구가 똑똑해야한다고 생각하지만 완전히 확신 할 수는 없습니다.

Verilog에서 원하는 것을 얻는 좋은 방법이 있습니까?

+0

http://www.project-veripage.com/ sv_structure.php –

+0

SystemVerilog 용입니다. SystemVerilog가 아닌 Verilog를 사용하고 있습니다. – seanmk

+2

복잡한 데이터 구조를 만들 때 Verilog는 매우 제한적입니다. 이것이 Verilog-2005 이후 IEEE에서 SystemVerilog로 대체 된 이유입니다. –

답변

1

당신은 항상 오히려 엔드 포인트보다 각 신호의 범위를 정의하기 위해 매크로를 사용하여 조금 더 당신에게 아이디어를 확장 할 수 있습니다 : 물론

`define WIDTH 41 
`define sigA 0:0 
`define sigB 1:1 
`define sigC 2:2 
`define sigD 8:3 
`define sigE 40:9 

module mymodule(signal_bus_in, signal_bus_out); 

    input wire [`WIDTH-1 : 0] signal_bus_in; 
    output reg [`WIDTH-1 : 0] signal_bus_out; 

    ... 
    // signal a 
    signal_bus_in[`sigA]; 
    // signal d 
    signal_bus_in[`sigD]; 
    ... 

, 이러면를 쉽게로 SystemVerilog를 포장 구조체로 (이유입니다 그들은 존재합니다!), 그러나 그것은 당신이 원하는 것을 위해 작동 할 것입니다. 또한이 명령은 라인에 추가되었지만 그렇게하지 않는 구조는 없습니다. 구조체조차도 신호에 순서를 추가합니다. 그러나 매크로를 사용하는 한, 마르코스를 정의 할 때를 제외하고는 순서가 중요하지 않습니다.

좋은 합성 도구는 아무 것도 구동시키지 않거나 아무 것도 몰지 않는 포트 나 와이어를 버릴 수 있어야하므로, 어떤 이유로 무시할 줄을 명시하지 않는 한 걱정할 필요가 없습니다. 사용되지 않는 모듈 핀을위한 여분의 공간을 합성합니다.

+0

줄에 명령을 추가하는 매크로가 걱정되지 않습니다. 가장 중요한 비트를 찾으려면 다음 신호가 무엇인지 알 필요가 없습니다. 귀하의 제안은이를 성취하므로 제 목적에 충분할 것입니다. – seanmk

1

Verilog에는 구조체가 없습니다. IMO는 긴 벡터의 모든 신호를 결합합니다 (또는 버스라고 부름). 그러나, 당신은 약간 매크로를 개선 할 수 있습니다

`define SIGNAL_BUS_WIDTH 41 
`define A 0:0 
`define B 1:1 
`define C 2:2 
`define D 8:3 
`define E 40:9 

// reference a 
signal_bus_in[`A] 
// reference d 
signal_bus_in[`D] 
// reference e 
signal_bus_in[`E] 

대부분의 합성 툴은 연결되지 않은 전선에 대한 별도의 로직을 작성하고 그나마 신경로 취급하지 않습니다.

1

전처리기를 너무 많이 사용하지 않으려면 구조를 시뮬레이트하기 위해 localparamfunction 선언을 사용해보십시오. 다음은이 아이디어를 설명하기 위해 다양한 크기의 A ~ D라는 네 개의 필드가있는 "mybus"구조의 모형입니다.

이러한 보조 매개 변수와 기능을이 버스 종류를 구성하고 제거해야하는 다양한 모듈에서만 include 파일에 넣을 수 있습니다.이것은 아마도 충돌에 대한 두려움없이 짧은 이름을 사용할 수있게 해줍니다.

module test ; 


// Boilerplate structure size definitions -- you could automatically generate these 
// with a simple script and put them into an include file. 

localparam mybus_a_size = 4; 
localparam mybus_a_offset = 0; 

localparam mybus_b_size = 8; 
localparam mybus_b_offset = mybus_a_offset + mybus_a_size; 

localparam mybus_c_size = 4; 
localparam mybus_c_offset = mybus_b_offset + mybus_b_size; 

localparam mybus_d_size = 6; 
localparam mybus_d_offset = mybus_c_offset + mybus_c_size; 

localparam mybus_size = mybus_a_size + mybus_b_size + mybus_c_size + mybus_d_size; 


// accessor functions, i.e., instead of bus.a you write mybus_a(bus) 

function [mybus_a_size-1:0] mybus_a (input [mybus_size-1:0] in); 
    mybus_a = in[mybus_a_size + mybus_a_offset - 1 : mybus_a_offset]; 
endfunction 

function [mybus_b_size-1:0] mybus_b (input [mybus_size-1:0] in); 
    mybus_b = in[mybus_b_size + mybus_b_offset - 1 : mybus_b_offset]; 
endfunction 

function [mybus_c_size-1:0] mybus_c (input [mybus_size-1:0] in); 
    mybus_c = in[mybus_c_size + mybus_c_offset - 1 : mybus_c_offset]; 
endfunction 

function [mybus_d_size-1:0] mybus_d (input [mybus_size-1:0] in); 
    mybus_d = in[mybus_d_size + mybus_d_offset - 1 : mybus_d_offset]; 
endfunction 


// constructor function -- build a mybus out of its components 

function [mybus_size-1:0] make_mybus(input [mybus_a_size-1:0] a, 
             input [mybus_b_size-1:0] b, 
             input [mybus_c_size-1:0] c, 
             input [mybus_d_size-1:0] d); 
    make_mybus = {d,c,b,a}; 
endfunction 


// example of using this stuff 

reg [mybus_size - 1 : 0] bus; 

initial begin 
    bus = make_mybus(1,2,3,4); 
    $display("Hello, my bus is { a=%b, b=%b, c=%b, d=%b }", mybus_a(bus), mybus_b(bus), mybus_c(bus), mybus_d(bus)); 
end 

endmodule 

이 모의 테스트는 좋은 출발점이 될 수 있습니다. 몇 가지 분명한 개선점은 간단한 스크립트에서이 보일러 플레이트를 자동으로 생성하고 C++에서 "setters"와 같은 추가 생성자 함수를 추가하는 것입니다. 즉

set_mybus_a(mybus, 5) // set mybus.a = 5 
관련 문제