본문 바로가기

VERILOG

ZCU102-G + AD7606C18 Simultaneous Sampling ADC 8ch 18Bit -3 parallel

 

ADC데이터를 받아 UART 전송하기 위한 모듈입니다.

 

`timescale 1ns / 1ps  // 시뮬레이션 스케일 설정

//이 모듈은 ADC 데이터와 채널 정보를 UART 전송 가능한 ASCII 문자로 변환하는 역할을 합니다.
//uart_ad는 UART를 통해 전송할 ASCII 문자를 저장하는 배열입니다.
//모듈은 UART 전송 프로세스를 제어하기 위한 상태 머신(uart_stat 및 uart_cnt)을 사용합니다.
//각 채널에 대한 ASCII 문자는 uart_ad에 저장되며, 모듈은 UART 인터페이스를 통해 이 문자들을 하나씩 전송합니다.
//모듈에는 UART 전송을 제어하기 위한 일정한 대기 기간이 있습니다.
module uart(
    input clk50,       // 50MHz 클럭 입력
    input reset_n,     // 리셋 신호, active-low
    
    input [17:0] ch1_dec,
    input [17:0] ch2_dec,
    input [17:0] ch3_dec,
    input [17:0] ch4_dec,
    input [17:0] ch5_dec,
    input [17:0] ch6_dec,
    input [17:0] ch7_dec,
    input [17:0] ch8_dec,    
    
    input [7:0] ch1_sig,
    input [7:0] ch2_sig,
    input [7:0] ch3_sig,
    input [7:0] ch4_sig,
    input [7:0] ch5_sig,
    input [7:0] ch6_sig,
    input [7:0] ch7_sig,
    input [7:0] ch8_sig,
    
    output tx           // UART 전송 출력
);

/********************************************/
// 상수 및 문자열 정의
/********************************************/
reg [7:0] uart_ad [113:0];  // ASCII 문자를 저장하는 배열
/********************************************/
// UART 전송을 위한 상태 머신
/********************************************/
reg [15:0] uart_cnt;  // UART 전송을 제어하기 위한 카운터
reg [2:0] uart_stat;  // UART 전송 상태

reg [7:0] txdata;      // 전송할 데이터
reg wrsig;             // UART 전송 신호

reg [8:0] k;           // 인덱스 카운터

reg [15:0] Time_wait;  // 대기 시간을 설정하는 카운터

always @(clk)
begin
    // 상태가 000일 때 ASCII 문자 설정
    if(uart_stat==3'b000) begin
        uart_ad[0]<=65;  // 'A'
        uart_ad[1]<=68;  // 'D'
        // ... (각 채널 및 문자 설정)
        uart_ad[113]<=13; // 캐리지 리턴 (CR)
    end
    // ... (다른 상태에 대한 설정)
end



always @(posedge clk)
begin
    // 리셋 시 초기화
    if(!reset_n) begin
        uart_cnt <= 0;
        uart_stat <= 3'b000;
        k <= 0;
    end
    else begin
        // 상태 머신
        case(uart_stat)
            // 상태 000: 대기 상태
            3'b000: begin
                // 대기 시간이 16비트 최댓값에 도달하면 상태 변경
                if (Time_wait == 16'hffff) begin
                    uart_stat <= 3'b001;
                    Time_wait <= 0;
                end
                else begin
                    uart_stat <= 3'b000;
                    Time_wait <= Time_wait + 1'b1;
                end
            end
            // ... (다른 상태에 대한 설정)
        endcase
    end
end

/********** 클럭 분주 모듈 ***********/
clkdiv u0 (
    .clk50 (clk50),
    .clkout (clk)
);

/************* UART 전송 모듈 ************/
uarttx u1 (
    .clk (clk),
    .datain (txdata),
    .wrsig (wrsig),
    .idle (idle),
    .tx (tx)
);

endmodule

 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    clkdiv 
//50MHz의 입력 클럭(clk50)을 받아서 분주된 클럭(clkout)을 만드는 Verilog 모듈입니다. 
//50MHz의 클럭을 이용하여 162 사이클 동안 클럭을 높은 상태로 유지한 후, 
//그 다음 163 사이클 동안 클럭을 낮은 상태로 유지하여 출력 클럭을 생성합니다. 
//이러한 동작을 반복하면서 50MHz 클럭을 분주하여 새로운 클럭을 만듭니다.
//////////////////////////////////////////////////////////////////////////////////
module clkdiv(clk50, clkout);
input clk50;            // 50MHz 클럭 입력
output clkout;          // 분주된 클럭 출력
reg clkout;             // 출력된 클럭 레지스터
reg [15:0] cnt;          // 16비트 카운터

always @(posedge clk50) // 50MHz 클럭의 상승 에지에서 동작
begin
  if(cnt == 16'd162)    // 카운터 값이 162인 경우
  begin
    clkout <= 1'b1;     // 출력 클럭을 높은 상태로 설정
    cnt <= cnt + 16'd1;  // 카운터를 1 증가
  end
  else if(cnt == 16'd325) // 카운터 값이 325인 경우
  begin
    clkout <= 1'b0;      // 출력 클럭을 낮은 상태로 설정
    cnt <= 16'd0;        // 카운터를 초기화
  end
  else
  begin
    cnt <= cnt + 16'd1;  // 그 외의 경우에는 카운터를 1 증가
  end
end
endmodule

 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    uarttx 
//UART 통신에서 데이터를 전송하는 모듈을 구현한 Verilog 코드입니다. 
//cnt라는 8비트 카운터를 사용하여 데이터 비트와 스톱 비트를 제어하며, 
//paritymode에 따라 패리티 비트를 계산합니다.
//////////////////////////////////////////////////////////////////////////////////
module uarttx(clk, datain, wrsig, idle, tx);
input clk;                // UART 클럭 입력
input [7:0] datain;       // 전송할 8비트 데이터 입력
input wrsig;              // 전송 신호 (1 사이클 동안 유효)
output idle;              // 전송이 끝났을 때 high, 전송 중일 때 low
output tx;                // UART 전송 데이터 출력
reg idle, tx;              // 전송 상태 및 출력 데이터 레지스터
reg send;                  // 전송 중인지 여부를 나타내는 레지스터
reg wrsigbuf, wrsigrise;   // wrsig 신호와 그 변화 여부를 나타내는 레지스터
reg presult;               // 패리티 비트 계산 결과를 나타내는 레지스터
reg[7:0] cnt;              // 8비트 전송을 위한 카운터
parameter paritymode = 1'b0; // 패리티 모드 (0: 짝수 패리티, 1: 홀수 패리티)

// wrsig 신호와 그 변화 여부를 나타내는 레지스터 업데이트
always @(posedge clk)
begin
   wrsigbuf <= wrsig;
   wrsigrise <= (~wrsigbuf) & wrsig;
end

// 전송 동작을 수행하는 블록
always @(posedge clk)
begin
  if (wrsigrise && (~idle))  // wrsig가 상승 에지에서 변하고 현재 전송이 끝나지 않았을 때
  begin
     send <= 1'b1;           // 전송 시작
  end
  else if(cnt == 8'd168)     // 8비트 전송이 끝나면
  begin
     send <= 1'b0;           // 전송 종료
  end
end

// 전송 동작을 수행하는 블록
always @(posedge clk)
begin
  if(send == 1'b1)  begin
    case(cnt)               // 카운터 값에 따라 동작 수행
    8'd0: begin
         tx <= 1'b0;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd16, 8'd32, 8'd48, 8'd64, 8'd80, 8'd96, 8'd112, 8'd128: begin
         tx <= datain[cnt/16];  // 데이터 비트 설정
         presult <= datain[cnt/16] ^ presult;  // 패리티 비트 계산
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd144: begin
         tx <= presult;        // 패리티 비트 설정
         presult <= datain[0] ^ paritymode;  // 다음 패리티 비트 계산을 위한 초기화
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd160: begin
         tx <= 1'b1;           // 스톱 비트 설정
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd168: begin
         tx <= 1'b1;           // 스톱 비트 설정
         idle <= 1'b0;         // 전송 종료 상태 설정
         cnt <= cnt + 8'd1;
    end
    default: begin
          cnt <= cnt + 8'd1;
    end
   endcase
  end
  else  begin
    tx <= 1'b1;
    cnt <= 8'd0;
    idle <= 1'b0;
  end
end
endmodule