iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0
Claude AI

用 Claude 帶我 Bring Up AI 開發板:30 天人機協作實錄系列 第 22 篇

[Day 22] 初學Vivado! Claude Code會嗎?

  • 分享至 

  • xImage
  •  

雖然程式設計都交給Claude Code, 但這麼龐大的軟體安裝還是要自己來才行,畢竟建環境這件事是每個新手一定要go through的過程:

Vivado安裝及使用可以參考底下兩篇,這邊就不做教學:

AMD(Xilinx) Vivado 安裝教學(伴伴學)
2018鐵人賽文章 [Day2] tool安裝

簡單的說,就是把Claude Code產生的Verilog程式碼貼上執行,再燒錄到板子上, 這邊好玩的地方是筆者這邊是用兩塊板子,所以有tx跟rx兩支.v的程式,要分別燒錄到Board A跟Board B:

Verilog Code top_tx.v for Board A

module top_rx(
    input sysclk,
    input pio1_in,      // 通道 1 輸入 (Pin 1)
    input pio2_in,      // 通道 2 輸入 (Pin 2)
    output uart_txd_out,// UART 輸出
    output [1:0] led    // 狀態指示燈
    );

    // 1. 生成 100MHz
    wire clk_100m;
    clk_wiz_0 clk_gen (.clk_in1(sysclk), .clk_out1(clk_100m));

    // ==========================================
    // 通道 1 處理邏輯
    // ==========================================
    reg sig1_s1, sig1_s2;
    always @(posedge clk_100m) begin
        sig1_s1 <= pio1_in;
        sig1_s2 <= sig1_s1;
    end
    wire sig1_rising = (sig1_s1 && !sig1_s2);

    reg [31:0] cnt1_raw;
    reg [31:0] freq1_res;

    // ==========================================
    // 通道 2 處理邏輯
    // ==========================================
    reg sig2_s1, sig2_s2;
    always @(posedge clk_100m) begin
        sig2_s1 <= pio2_in;
        sig2_s2 <= sig2_s1;
    end
    wire sig2_rising = (sig2_s1 && !sig2_s2);

    reg [31:0] cnt2_raw;
    reg [31:0] freq2_res;

    // ==========================================
    // 系統計時與心跳
    // ==========================================
    reg [31:0] timer_1s;
    localparam TIME_1S = 100000000;
    reg update_flag;
    reg heartbeat_toggle; // 用來讓 LED 閃爍的暫存器

    always @(posedge clk_100m) begin
        if (timer_1s == TIME_1S - 1) begin
            timer_1s <= 0;
            freq1_res <= cnt1_raw;
            freq2_res <= cnt2_raw;
            cnt1_raw <= 0;
            cnt2_raw <= 0;
            update_flag <= 1;
            heartbeat_toggle <= ~heartbeat_toggle; // 每秒翻轉一次狀態
        end else begin
            timer_1s <= timer_1s + 1;
            update_flag <= 0;
            
            if (sig1_rising) cnt1_raw <= cnt1_raw + 1;
            if (sig2_rising) cnt2_raw <= cnt2_raw + 1;
        end
    end

    // ==========================================
    // UART 發送邏輯 (雙通道)
    // ==========================================
    reg [7:0] tx_data;
    reg tx_start;
    wire tx_busy;
    
    uart_tx my_uart (
        .clk(clk_100m),
        .start(tx_start),
        .data(tx_data),
        .tx_busy(tx_busy),
        .tx_pin(uart_txd_out)
    );

    reg [4:0] send_step;
    
    always @(posedge clk_100m) begin
        tx_start <= 0;
        
        if (update_flag) begin
            send_step <= 1; 
        end
        
        if (send_step != 0 && !tx_busy) begin
            case (send_step)
                // Header (0xAA)
                1: begin tx_data <= 8'hAA; tx_start <= 1; send_step <= 2; end 
                
                // Channel 1 Data
                2: if(!tx_start) begin tx_data <= freq1_res[31:24]; tx_start <= 1; send_step <= 3; end 
                3: if(!tx_start) begin tx_data <= freq1_res[23:16]; tx_start <= 1; send_step <= 4; end 
                4: if(!tx_start) begin tx_data <= freq1_res[15:8];  tx_start <= 1; send_step <= 5; end 
                5: if(!tx_start) begin tx_data <= freq1_res[7:0];   tx_start <= 1; send_step <= 6; end 

                // Channel 2 Data
                6: if(!tx_start) begin tx_data <= freq2_res[31:24]; tx_start <= 1; send_step <= 7; end 
                7: if(!tx_start) begin tx_data <= freq2_res[23:16]; tx_start <= 1; send_step <= 8; end 
                8: if(!tx_start) begin tx_data <= freq2_res[15:8];  tx_start <= 1; send_step <= 9; end 
                9: if(!tx_start) begin tx_data <= freq2_res[7:0];   tx_start <= 1; send_step <= 10; end 

                // Tail (0x55)
                10: if(!tx_start) begin tx_data <= 8'h55; tx_start <= 1; send_step <= 0; end 
            endcase
        end
    end

    // ==========================================
    // LED 顯示邏輯 (視覺回饋區)
    // ==========================================
    // LED 0 (Signal): 只要任一通道有頻率輸入 (>1kHz),這顆燈就會亮
    assign led[0] = (freq1_res > 1000) || (freq2_res > 1000); 
    
    // LED 1 (System): 只要系統還活著,這顆燈就會每秒閃爍一次 (Heartbeat)
    // 另外加上 update_flag 讓傳輸瞬間閃一下,增加科技感
    assign led[1] = heartbeat_toggle; 
    
endmodule

Verilog Code top_rx.v for Board B

module top_rx(
    input sysclk,
    input pio1_in,      // 通道 1 輸入
    input pio2_in,      // 通道 2 輸入 (新增)
    output uart_txd_out,// UART 輸出
    output [1:0] led
    );

    // 1. 生成 100MHz
    wire clk_100m;
    clk_wiz_0 clk_gen (.clk_in1(sysclk), .clk_out1(clk_100m));

    // ==========================================
    // 通道 1 處理邏輯 (Pin 1)
    // ==========================================
    reg sig1_s1, sig1_s2;
    always @(posedge clk_100m) begin
        sig1_s1 <= pio1_in;
        sig1_s2 <= sig1_s1;
    end
    wire sig1_rising = (sig1_s1 && !sig1_s2);

    reg [31:0] cnt1_raw;
    reg [31:0] freq1_res; // 結果 1

    // ==========================================
    // 通道 2 處理邏輯 (Pin 2) - 完全複製一份硬體電路
    // ==========================================
    reg sig2_s1, sig2_s2;
    always @(posedge clk_100m) begin
        sig2_s1 <= pio2_in;
        sig2_s2 <= sig2_s1;
    end
    wire sig2_rising = (sig2_s1 && !sig2_s2);

    reg [31:0] cnt2_raw;
    reg [31:0] freq2_res; // 結果 2

    // ==========================================
    // 共用計時器 (1秒)
    // ==========================================
    reg [31:0] timer_1s;
    localparam TIME_1S = 100000000;
    reg update_flag;

    always @(posedge clk_100m) begin
        if (timer_1s == TIME_1S - 1) begin
            timer_1s <= 0;
            // 同時鎖存兩個結果
            freq1_res <= cnt1_raw;
            freq2_res <= cnt2_raw;
            // 重置兩個計數器
            cnt1_raw <= 0;
            cnt2_raw <= 0;
            update_flag <= 1;
        end else begin
            timer_1s <= timer_1s + 1;
            update_flag <= 0;
            
            // 並行計數:這兩個 if 語句是同時執行的,互不影響
            if (sig1_rising) cnt1_raw <= cnt1_raw + 1;
            if (sig2_rising) cnt2_raw <= cnt2_raw + 1;
        end
    end

    // ==========================================
    // UART 發送邏輯 (擴充為發送 2 個數據)
    // ==========================================
    reg [7:0] tx_data;
    reg tx_start;
    wire tx_busy;
    
    uart_tx my_uart (
        .clk(clk_100m),
        .start(tx_start),
        .data(tx_data),
        .tx_busy(tx_busy),
        .tx_pin(uart_txd_out)
    );

    reg [4:0] send_step;
    
    always @(posedge clk_100m) begin
        tx_start <= 0;
        
        if (update_flag) begin
            send_step <= 1; 
        end
        
        if (send_step != 0 && !tx_busy) begin
            case (send_step)
                // Header
                1: begin tx_data <= 8'hAA; tx_start <= 1; send_step <= 2; end 
                
                // --- 發送 Freq 1 (4 Bytes) ---
                2: if(!tx_start) begin tx_data <= freq1_res[31:24]; tx_start <= 1; send_step <= 3; end 
                3: if(!tx_start) begin tx_data <= freq1_res[23:16]; tx_start <= 1; send_step <= 4; end 
                4: if(!tx_start) begin tx_data <= freq1_res[15:8];  tx_start <= 1; send_step <= 5; end 
                5: if(!tx_start) begin tx_data <= freq1_res[7:0];   tx_start <= 1; send_step <= 6; end 

                // --- 發送 Freq 2 (4 Bytes) - 新增 ---
                6: if(!tx_start) begin tx_data <= freq2_res[31:24]; tx_start <= 1; send_step <= 7; end 
                7: if(!tx_start) begin tx_data <= freq2_res[23:16]; tx_start <= 1; send_step <= 8; end 
                8: if(!tx_start) begin tx_data <= freq2_res[15:8];  tx_start <= 1; send_step <= 9; end 
                9: if(!tx_start) begin tx_data <= freq2_res[7:0];   tx_start <= 1; send_step <= 10; end 

                // Tail
                10: if(!tx_start) begin tx_data <= 8'h55; tx_start <= 1; send_step <= 0; end 
            endcase
        end
    end

    assign led[0] = (freq1_res > 1000); 
    assign led[1] = (freq2_res > 1000); // 現在兩顆燈分別監控兩個通道
    
endmodule

上一篇
[Day 21] 哇!要設計IC了!
下一篇
[Day 23] 環境架好了,然後呢? 設定腳位約束 Constraints / XDC
系列文
用 Claude 帶我 Bring Up AI 開發板:30 天人機協作實錄 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言