Verilog/Verilog 실습

Verilog ADC로 전압값을 BCD로 변환

오버헤드프레스 2023. 5. 4. 15:35

 

 

 

 

 

 

[15:0] do_out

[15:0] do_out, 16비트라고 나오지만 12bit를 사용한다.

오차범위는 1/4096. bit가 클수록 오차가 작아진다.

 

 

전압값을 BCD로 변환해서 7세그먼트에 출력하는 코드

`timescale 1ns / 1ps


module ch6_ADC_top(
    input vauxp6,
    input vauxn6,
    input clk,
    output [3:0] com_an,
    output [6:0] seg
    );
    
    reg [11:0] adc_value;
    wire [15:0] bcd;
    wire [4:0] channel_out;
    wire [15:0] do_out;
    wire eoc_out;
    
    xadc_wiz_0 adc_ch6(
          .daddr_in({2'b00, channel_out}),            // Address bus for the dynamic reconfiguration port, DRC device에서 쓰는 address
          //channel_out보다 2 bit 많아서 상위 2bit를 0으로 채워줌
          .dclk_in(clk),             // Clock input for the dynamic reconfiguration port, 통신에 필요한 clk
          .den_in(eoc_out),              // Enable Signal for the dynamic reconfiguration port
//          di_in,               // Input data bus for the dynamic reconfiguration port, data port에 들어가는 data
//          dwe_in,              // Write Enable for the dynamic reconfiguration port, register에서 사용했던 wr_e_d과 같음
          .reset_in(1'b0),            // Reset signal for the System Monitor control logic
          .vauxp6(vauxp6),              // Auxiliary channel 6 입력 핀, 전압을 읽어들임 
          .vauxn6(vauxn6),              //입력 핀
//          busy_out,            // ADC Busy signal 측정할 때 1이 나옴
          .channel_out(channel_out),         // Channel Selection Outputs
          .do_out(do_out),              // Output data bus for dynamic reconfiguration port, convert한 측정값이 나오는 것
//          drdy_out,            // Data ready signal for the dynamic reconfiguration port
          .eoc_out(eoc_out)             // End of Conversion Signal
//          eos_out,             // End of Sequence Signal 시퀀스 시그널이 끝날 때 1
//          alarm_out,           // OR'ed output of all the Alarms    
//          vp_in,               // Dedicated Analog Input Pair
//          vn_in
            );
    
//    assign adc_value = eoc_out ? do_out[15:4] : adc_value;

    always @(posedge eoc_out)begin
        adc_value = do_out[15:4];
    end
    
    
    bin_to_dec btd(.bin({adc_value}), .bcd(bcd));  //adc_value가 do_out의 상위 12비트

    FND_4digit_switcher fnd(
    .value_1(bcd[3:0]), 
    .value_10(bcd[7:4]), 
    .value_100(bcd[3:0]), 
    .value_1000(bcd[7:4]),
    .clk(clk),
    .com_an(com_an),
    .seg(seg)
    );
    
    
    
    
    
    
    
endmodule

 

0~4095까지 가변저항을 통해 제어

 

 

0~1023까지를 소수점으로 표현하기

 

 

7세그먼트 7번째 비트 활성화 코드

 

`timescale 1ns / 1ps


module FND_4digit_switcher( // 1ms에 1번씩 com_an 단자 바꿔줌
    input [3:0] value_1,
    input [3:0] value_10,
    input [3:0] value_100,
    input [3:0] value_1000,
    input clk,
    output reg [3:0] com_an = 4'b1110,
    output [7:0] seg
    );
    

    wire clk_usec, clk_msec;
    reg seg_dp;
    reg [3:0] hex_value;
    
//    clock_usec UCLK (.clk(clk), .reset_n(1), .clk_usec(clk_usec));
//    clock_msec MCLK (.clk(clk), .clk_usec(clk_usec), .reset_n(1), .clk_msec(clk_msec));
    wire clk_160ns,clk_2560ns,clk_40us, clk_655us;
    
    clock_divider cd_16(.clk(clk), .sel(3), .clk_out(clk_160ns));  //160ns
    clock_divider cd_256(.clk(clk_160ns), .sel(3), .clk_out(clk_2560ns));  //2560ns
    clock_divider cd_4096(.clk(clk_2560ns), .sel(3), .clk_out(clk_40us));  //40us
    clock_divider cd_8192(.clk(clk_40us), .sel(3), .clk_out(clk_655us));  //655us
    
    decoder_7_seg dec7seg(.hex_value(hex_value), .seg(seg[6:0]));
    assign seg[7] = seg_dp; //7번째 bit가 .임
    
    always @(negedge clk_655us) begin
        case (com_an)
            4'b1110: begin
                com_an = 4'b1101;
                hex_value = value_10;
                seg_dp = 1;
            end
            4'b1101: begin
                com_an = 4'b1011;
                hex_value = value_100;
                seg_dp=1;
            end
            4'b1011: begin
                com_an = 4'b0111;
                hex_value = value_1000;
                seg_dp = 0;
            end
            4'b0111: begin
                com_an = 4'b1110;
                hex_value = value_1;
                seg_dp = 1;
            end
            default : begin
                com_an = 4'b1110;
                hex_value = value_1;
            end
        endcase
    end
    
endmodule

seg[7] = seg_dp로 주고 1000의 자리에서 0일 때 . 출력되게 한다.

 

 

ADC를 이용하여 전압값 BCD로 표현하는 코드

 

`timescale 1ns / 1ps


module ch6_ADC_top(
    input vauxp6,
    input vauxn6,
    input clk,
    output [3:0] com_an,
    output [7:0] seg
    );
    
    reg [11:0] adc_value;
    wire [15:0] bcd;
    wire [4:0] channel_out;
    wire [15:0] do_out;
    wire eoc_out;
    
    xadc_wiz_0 adc_ch6(
          .daddr_in({2'b00, channel_out}),            // Address bus for the dynamic reconfiguration port, DRC device에서 쓰는 address
          //channel_out보다 2 bit 많아서 상위 2bit를 0으로 채워줌
          .dclk_in(clk),             // Clock input for the dynamic reconfiguration port, 통신에 필요한 clk
          .den_in(eoc_out),              // Enable Signal for the dynamic reconfiguration port
//          di_in,               // Input data bus for the dynamic reconfiguration port, data port에 들어가는 data
//          dwe_in,              // Write Enable for the dynamic reconfiguration port, register에서 사용했던 wr_e_d과 같음
          .reset_in(1'b0),            // Reset signal for the System Monitor control logic
          .vauxp6(vauxp6),              // Auxiliary channel 6 입력 핀, 전압을 읽어들임 
          .vauxn6(vauxn6),              //입력 핀
//          busy_out,            // ADC Busy signal 측정할 때 1이 나옴
          .channel_out(channel_out),         // Channel Selection Outputs
          .do_out(do_out),              // Output data bus for dynamic reconfiguration port, convert한 측정값이 나오는 것
//          drdy_out,            // Data ready signal for the dynamic reconfiguration port
          .eoc_out(eoc_out)             // End of Conversion Signal
//          eos_out,             // End of Sequence Signal 시퀀스 시그널이 끝날 때 1
//          alarm_out,           // OR'ed output of all the Alarms    
//          vp_in,               // Dedicated Analog Input Pair
//          vn_in
            );
    
//    assign adc_value = eoc_out ? do_out[15:4] : adc_value;

    always @(posedge eoc_out)begin
        adc_value = do_out[15:6]; 
    end
    
    
    bin_to_dec btd(.bin({adc_value}), .bcd(bcd));  //adc_value가 do_out의 상위 12비트

    FND_4digit_switcher fnd(
    .value_1(bcd[3:0]), 
    .value_10(bcd[7:4]), 
    .value_100(bcd[11:8]), 
    .value_1000(bcd[15:12]),
    .clk(clk),
    .com_an(com_an),
    .seg(seg)
    );

    
endmodule

 

코드 실행 결과

 

7세그먼트 7번째 비트의 사용으로 0~1023까지 출력 가능

 

'Verilog > Verilog 실습' 카테고리의 다른 글

Verilog 다목적 시계  (0) 2023.05.16
Verilog HC-SR04 초음파센서 제어  (0) 2023.05.16
Verilog [CPU만들기] ACC  (2) 2023.05.16
Verilog [CPU 만들기] PC, ALU  (0) 2023.05.09
Verilog basys3으로 DHT11 제어하기  (0) 2023.05.03