왕초보 대학교 과제 Verilog 코드 질문

23.12.02 03:56 작성 조회수 270

0

안녕하세요? 대학교 과제로 Up and Down game을 만들어보려고 코드를 짜봤는데 모델심에서 시뮬레이션을 돌리면 에러가 떠서 이렇게 도움을 받고자..질문드립니다 동작만 가능하게 만들면 되어서 마음껏 수정하셔도 괜찮아요 (뭔가 제가 짠 게 비효율적인 것 같아서요..)

아래는 제가 짠 코드들 이구요, 전체적인 동작은 다음과 같습니다. 1. State0에서 module LSFR을 불러와서 난수 rnd를 저장하고 State1로 넘어간다. 2. State1에서는 사용자에게 fpga보드의 스위치를 통해 4비트의 이진수 sw을 입력받고 bcd에 저장한다. 그러고나서 module bcd_seven을 불러와서 fpga보드의 숫자판에 seven을 출력하고 State2로 넘어간다. 3. State3는 rnd와 bcd 값을 비교하는 부분이다. 만약 rnd > bcd인 경우, led 에서 Red 불빛을 키고 다시 State1로 간다. 그렇지 않고 만약 rnd < bcd인 경우, led에서 Blue 불빛을 키고 State1로 간다. 그렇지 않고 rnd = bcd인 경우, led에서 Green 불빛을 키고 다시 State0으로 간다.

ㄱ. 사용자로부터 입력받은 4bit 스위치 값을 fpga보드 위에 숫자판에 0~9까지의 숫자로 표시하는 bcd_seven 모듈

`timescale 1ns/1ns

module bcd_seven

input [3:0] bcd;

output [6:0] seven;

reg [6:0] seven;

always @(bcd)

begin

case (bcd)

4'b0000 : seven = 7'b0111111;

4'b0001 : seven = 7'b0000110;

4'b0010 : seven = 7'b1011011;

4'b0011 : seven = 7'b1001111;

4'b0100 : seven = 7'b1100110;

4'b0101 : seven = 7'b1101101;

4'b0110 : seven = 7'b1111101;

4'b0111 : seven = 7'b0000111;

4'b1000 : seven = 7'b1111111;

4'b1001 : seven = 7'b1101111;

default : seven = 7'b0000000;

endcase

end

endmodule

ㄴ. 0~9까지의 숫자 중 하나를 랜덤으로 뽑아 rnd에 저장하는 LSFR 모듈

`timescale 1ns/1ns

module LFSR (input clk, input rst, output [3:0] rnd);

reg [3:0] random, random_next, random_done;

reg [2:0] count, count_next;

wire feedback = random[3] ^ random[2];

always @(posedge clk or posedge rst) begin

if (rst) begin

random <= 4'hF;

count <= 0;

end

else if (count == 3) begin

count <= 0;

// if (random < 10) // Limit the range to 0 to 9

random_done <= random % 10;

end

else begin

random <= random_next;

count <= count_next;

end

end

always @(*) begin

random_next = random;

count_next = count;

random_next = {random[2:0], feedback};

count_next = count + 1;

end

assign rnd = random_done;

endmodule

ㄷ. rnd와 bcd 값을 비교해서 led 불빛을 표시하는 Upanddown 모듈

`timescale 1ns/1ns

module Upanddown (

input clk,

input rst,

input [3:0] sw,

output reg red_led,

output reg blue_led,

output reg green_led

);

reg [3:0] rnd;

reg [3:0] bcd;

reg [1:0] state, next_state;

// Instantiate LSFR and bcd_seven modules

LSFR lsfr_inst (

.clk(clk),

.rst(rst),

.rnd(rnd)

);

bcd_seven bcd_seven_inst (

.bcd(sw),

.seven()

);

always @(posedge clk or posedge rst) begin

if (rst) begin

state <= 2'b00; // Initial state: State0

end else begin

state <= next_state;

end

end

always @(posedge clk) begin

case (state)

2'b00: begin

// State0: Generate rnd using LSFR

lsfr_inst; // Call LSFR module

rnd <= lsfr_inst.rnd; // Store the generated rnd

next_state = 2'b01; // Move to State1

end

2'b01: begin

// State1: Get user input from switch and display on 7-segment display

bcd_seven_inst.bcd <= sw;

bcd_seven_inst.seven(); // Call bcd_seven module

bcd <= bcd_seven_inst.bcd;

next_state = 2'b10; // Move to State2

end

2'b10: begin

// State2: Compare rnd and user input, update LEDs, and go to the next state

if (rnd > bcd) begin

red_led = 1;

blue_led = 0;

green_led = 0;

next_state = 2'b01; // Move to State1

end else if (rnd < bcd) begin

red_led = 0;

blue_led = 1;

green_led = 0;

next_state = 2'b01; // Move to State1

end else begin

red_led = 0;

blue_led = 0;

green_led = 1;

next_state = 2'b00; // Move to State0

end

end

default: begin

next_state = 2'b00; // Default: Move to State0

end

endcase

end

endmodule

ㄹ. rnd>bcd, rnd<bcd, rnd=bcd 등 전체적인 동작을 확인할 수 있는 테스트벤치

`timescale 1ns/1ns

module Upanddown_Tb;

reg clk;

reg rst;

reg [3:0] sw;

wire red_led, blue_led, green_led;

// Instantiate Upanddown module

Upanddown upanddown_inst (

.clk(clk),

.rst(rst),

.sw(sw),

.red_led(red_led),

.blue_led(blue_led),

.green_led(green_led)

);

// Clock generation

initial begin

clk = 0;

forever #5 clk = ~clk;

end

// Initial values

initial begin

rst = 1;

sw = 4'b0000;

// Apply reset

#10 rst = 0;

// Scenario 1: rnd > bcd

#20 sw = 4'b0010; // User input: 0010

#30 $display("Scenario 1: rnd > bcd, Expect Red LED: %0d, Blue LED: %0d, Green LED: %0d", red_led, blue_led, green_led);

// Scenario 2: rnd < bcd

#40 sw = 4'b1001; // User input: 1001

#50 $display("Scenario 2: rnd < bcd, Expect Red LED: %0d, Blue LED: %0d, Green LED: %0d", red_led, blue_led, green_led);

// Scenario 3: rnd = bcd

#60 sw = 4'b1101; // User input: 1101

#70 $display("Scenario 3: rnd = bcd, Expect Red LED: %0d, Blue LED: %0d, Green LED: %0d", red_led, blue_led, green_led);

#100 $finish; // End simulation after some time

end

endmodule

 

답변 1

답변을 작성해보세요.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.12.03

안녕하세요, 인프런 AI 인턴입니다. gdwkld0324님, Verilog 코드 질문에 답변드리겠습니다.

모델심 시뮬레이션이 에러를 발생시킨 원인은 구체적인 에러 메시지를 보지 않고 정확히 파악하기 어렵지만, 제공해주신 코드를 기반으로 몇 가지 잠재적 문제점에 대해 말씀드릴 수 있습니다:

  1. Module 인스턴스 호출 방식이 올바르지 않습니다.
    Verilog에서 module을 호출할 때는 함수처럼 호출할 수 없습니다. inst_name.module_name(); 같은 형식은 올바른 Verilog 문법이 아닙니다.
    대신 아래와 같이 module을 정의하고 ports를 연결하여 인스턴스를 생성합니다:

    lsfr lsfr_inst(
       .clk(clk),
       .rst(rst),
       .rnd(rnd)
    );
    
  2. State 머신 설계에 문제가 보입니다.
    현재 상태를 바탕으로 다음 상태 및 LED를 설정하는 모든 로직이 posedge clk만 확인하고 있습니다. always @(posedge clk) 블록을 사용하여 이러한 처리를 하도록 수정해야 합니다. 상태 변경을 위해 민감한 신호들을 항상 블록의 트리거에 포함시켜야 합니다.

  3. 비동기적 리셋의 사용 (posedge 블록에 rst 신호가 포함되어 있는 경우)
    rst 신호를 비동기 리셋으로 사용하려면 다음과 같이 모든 always 블록에 포함시켜야 합니다:

    always @(posedge clk or posedge rst) begin
       if (rst) begin
           // reset logic
       end else begin
           // normal logic
       end
    end
    

    위의 조건으로 초기 상태 설정 및 기기 상태의 리셋을 포함시킬 수 있습니다.

  4. Upanddown 모듈 내의 LSFR 모듈과 bcd_seven 모듈 인스턴스가 중첩된 always 블록에서 등장하지 않아야 합니다. 여기서 모듈 인스턴스는 상위 블록 안에 한 번만 선언되어야 합니다.

  5. 시뮬레이션 명령인 $display 문은 모듈의 내부 로직이 아니라 testbench에서 결과를 출력하기 위한 용도로 사용됩니다. 저 결과 메시지들은 Upanddown 모듈 자체에 있어서는 안 되고 Upanddown_Tb 내에서만 사용되어야 합니다.

  6. 이 외에도 세부 로직에 문제가 있을 수 있으니 구체적 에러 메시지에 따라 추가적인 디버깅이 필요합니다.

위 사항들을 검토하여 코드 수정을 진행해보세요. 왕초보 대학교 과제를 잘 마무리하시길 바랍니다. Verilog 코딩에서 더 궁금한 점이 있으시다면 다시 질문해주시기 바랍니다.