2012-04-23 6 views
0

나는 combinational과 행동 논리의 혼합 주위에 내 머리를 싸려고합니다. 나는 4 개의 LED와 66 MHz 클럭 입력을 가진 작은 FPGA를 가지고있다. 아이디어는 두 개를 빛나게하는 것 (하나는 상승, 하나는 떨어 뜨림)과 또 다른 두 개는 깜박 거리게하는 것이었다. 그래서 나는 다음과 같은 코드를 내놓았다 :조합 및 행동 논리를 혼합하여 연속 할당을 최적화 하시겠습니까?

module ledflash(input wire CLK, 
     input wire USER_RESET, 
     output wire LED[3:0]); 

    reg [26:0]   cnt; 
    reg [4:0]   pwm; 

    wire    led_enable = ~USER_RESET; 

    always @(posedge CLK) 
    begin 
    if (led_enable) 
     begin 
     cnt <= cnt + 1; 
     pwm <= pwm[3:0] + (cnt[26] ? cnt[25:22] : ~cnt[25:22]); 
     end 
    else 
     begin 
     cnt <= 0; 
     pwm <= 0; 
     end 
    end 

    assign LED[0] = led_enable ? (cnt[26] ? pwm[4] : ~pwm[4]) : 0; 
    assign LED[1] = led_enable ? (cnt[26] ? ~pwm[4] : pwm[4]) : 0; 

    assign LED[2] = led_enable ? cnt[25] : 0; 
    assign LED[3] = led_enable ? ~cnt[25] : 0; 

endmodule 

내가 공급 업체 특정 DCM을 사용하지 않았고, 66MHz의 클럭에 간단 비트 가산기는 마법을 사용할 수 있습니다. 아마도 전체 설계가 처음부터 잘못되었습니다 (예를 들어, 두 개의 클럭 분배기를 사용하여 (거의 동일한)를 달성하기 위해 두 개의 레지스터를 약간 뒤집을 수 있었지만), 나는이 상황에 빠져 나를 궁금하게 만들었습니다. ..

일반 소프트웨어 개발자의 관점에서 보면 중복 할당 된 부분이 연속 할당되어 있습니다. 예를 들어, 여분의 레지스터가 사용될 수 있으므로 더 적은 작업이 수행되는 것처럼 보입니다. 예를 들어 :

module ledglow(input wire CLK, 
     input wire USER_RESET, 
     output wire LED[3:0]); 

    reg [26:0]   cnt; 
    reg [4:0]   pwm; 
    reg    led_pair1; 
    reg    led_pair2; 

    wire    led_enable = ~USER_RESET; 

    always @(posedge CLK) 
    begin 
    if (led_enable) 
     begin 
     cnt <= cnt + 1; 
     pwm <= pwm[3:0] + (cnt[26] ? cnt[25:22] : ~cnt[25:22]); 
     end 
    else 
     begin 
     cnt <= 0; 
     pwm <= 0; 
     end 
    led_pair1 <= cnt[26] ? pwm[4] : ~pwm[4]; 
    led_pair2 <= cnt[25]; 
    end 

    assign LED[0] = led_enable ? led_pair1 : 0; 
    assign LED[1] = led_enable ? ~led_pair1 : 0; 

    assign LED[2] = led_enable ? led_pair2 : 0; 
    assign LED[3] = led_enable ? ~led_pair2: 0; 

endmodule 

나는 위의 두 가지 방법에 대한 신디사이저 보고서 차이를 파고 HDL 회로도를보고하려고했지만, 나 같은 그러한 경험이 사람을 위해 그 방법이 너무 복잡합니다.

의심 할 여지없이 합성 도구가 조합 논리를 매우 잘 최적화하지만 우변 표현이 매우 복잡하여 단선 등이된다고 가정 할 때, 이와 같은 말을 할 수있는 방법이 있습니까?

if (some_reg_var) begin 
     assign net0 = 1; 
     assign net1 = 0; 
    end 
    else 
    begin 
     assign net0 = 0; 
     assign net1 = 1; 
    end 

아니면 그렇게하는 것이 합리적입니까? 그렇지 않은 경우, 그러한 경우에 행동 부분을 단순화하기 위해 레지스터를 도입하는 것이 합리적입니까? 최소한 규칙이나 엄지가 있다는 것이 확실합니다. 어떤 도움을 주셔서 감사합니다.

답변

2

귀하의 질문은 약간 장황하지만, 내가 뭘 잘못하고 있는지 이해하고 있다고 생각합니다.

always 블록의 reg와 비슷한 if/else 논리를 사용하기 위해 long assign 문을 분리 할 방법이 있는지 알고 싶습니까?

Verilog는 항상 이런 식으로 약간 우습게 보였습니다.하지만 'reg'데이터 유형 을 선언한다고해서 그것이 레지스터로 합성된다는 것을 의미하지는 않습니다. 실제로 저장할 상태가있는 경우에만 레지스터를 만듭니다. 2

wire a; 
wire b; 
assign a = b ? 0 : 1; 

케이스 :

reg a; 
wire b; 

always @(b) 
    if(b) 
     a <= 0; 
    else 
     a <= 1; 

이 모두가 동일한 로직을 작성해야합니다 (

사례 1 : 다음 두 명령문은 정확히 같은 일을 합성해야했다 가졌 간단히 a =! b 인 인버터. reg를 선언 한 두 번째 경우에도 실제로 기억할 항목이 없으므로 모든 입력이 민감도 목록에 있습니다.

이 때문에 복잡한 if/else 로직을 작성하여 코드를 단순화 할 수 있습니다. 그렇다고해서 추가 레지스터를 합성 할 때 벌칙을 지불하는 것은 아닙니다. 그래서 당신에게 가장 편한 방법을 자유롭게 쓰십시오. (항상 블록을 사용하는 경우 가능한 모든 경우에 대해 할당을했는지 확인하십시오. 그렇지 않으면 원하지 않는 래치를 추측 할 수 있습니다.)

+0

안녕하세요, Tim, 답변 해 주셔서 감사합니다.그래, 문제는 - 실제로 레지스터를 사용하지 않고 중복 된 조건을 피하는 방법입니다. 필자의 경우 실제로 자일링스 신시사이저는 약간 다른 코드를 생성했으며 2 개의 여분의 1 비트 레지스터와 몇 가지 다른 멀티플렉서를 사용했다. 그러나 그 외의 개략도는 매우 유사하게 보였다. 반면, 연속 할당은 매 클록 사이클마다 실행됩니다. 맞습니까? 예를 들어, 100 MHz에서 스트로브하는 시스템 클럭에 의해 구동되고 클럭 분배기가 있다고 가정하면 LED를 변경할 수있는 "로직"이 약간 낮은 속도로 실행됩니다. –

+0

블록으로 복잡한 로직을 넣을 수 있습니까? 분배기 출력에 의해 구동 됨으로써 회로에 의해 수행되는 전체 실행 단계/속도를 감소시키고, 아마도 소비자는 더 적은 에너지를 소비 할 것인가? 그럴 것 같아. 따라서 로직 자체가 공간을 덜 차지하지는 않습니다. 그냥 신디사이저 능가하는 방법이있을 수 있다고 생각 : –

+0

이것은 첫 번째 의견에 대한 회신입니다 : 당신이 좀 더 정교한 코드를 만들었고 2 개의 여분의 1 비트 레지스터를 사용 했습니까? 무엇보다 여분의 레지스터? 어떤 코드? 귀하의 다른 질문에 대한 지속적인 할당은 단지 '연속'입니다. 클럭주기와 아무런 관련이 없습니다. 연속 식 입력이 변경 될 때마다 출력이 즉시 변경됩니다 (또는 몇 피코 초 후에). – Tim