<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>FPGA &#8211; richliu&#039;s blog</title>
	<atom:link href="https://richliu.com/tag/fpga/feed/" rel="self" type="application/rss+xml" />
	<link>https://richliu.com</link>
	<description>Linux, 工作, 生活, 家人</description>
	<lastBuildDate>Fri, 19 Jun 2026 08:12:02 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>KianV Risc-V + Linux 7.1 uLinux</title>
		<link>https://richliu.com/2026/06/19/6546/kianv-risc-v-linux-7-1-ulinux/</link>
					<comments>https://richliu.com/2026/06/19/6546/kianv-risc-v-linux-7-1-ulinux/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Fri, 19 Jun 2026 08:12:00 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[RiscV]]></category>
		<category><![CDATA[隨手札記]]></category>
		<category><![CDATA[BusyBox]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Nommu]]></category>
		<category><![CDATA[RISC-V]]></category>
		<category><![CDATA[Tiny Tapeout]]></category>
		<category><![CDATA[uLinux]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6546</guid>

					<description><![CDATA[<p>最終目標就是要在 Tiny Tapeout (TT) 開一顆 SoC ，不過在這之前，我也想先做一些實驗，驗證 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/06/19/6546/kianv-risc-v-linux-7-1-ulinux/">KianV Risc-V + Linux 7.1 uLinux</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1375" height="427" src="https://richliu.com/wp-content/uploads/2026/06/image.png" alt="" class="wp-image-6547" srcset="https://richliu.com/wp-content/uploads/2026/06/image.png 1375w, https://richliu.com/wp-content/uploads/2026/06/image-600x186.png 600w, https://richliu.com/wp-content/uploads/2026/06/image-768x238.png 768w, https://richliu.com/wp-content/uploads/2026/06/image-816x253.png 816w" sizes="(max-width: 1375px) 100vw, 1375px" /></figure>



<p>最終目標就是要在 Tiny Tapeout (TT) 開一顆 SoC ，不過在這之前，我也想先做一些實驗，驗證這些想法是否可行。</p>



<p>KianRiscV 是一顆完整的 RISC-V CPU，也在 TT 開過 IC，但這顆對我們來說還是太大了（雖然說太大也只大一點）。為了省錢，而且這麼大顆也沒有必要，所以我們還是要縮小 Size。在 kianRiscV/linux_socs/kianv_harris_mcycle_edition 下，看說明是在 ULX3S 85F（FPGA Lattice ECP5 LFE5U-85F-6BG381C，有 Open Source 的 Tool）下也可以執行的 uLinux RISC-V CPU core，不僅符合我的目標，而且對我超級友善啊。</p>



<p>裡面還有預設的 Linux kernel 6.1.14 和一個 busybox initramfs，不過我就想，要就做全套嘛，不如把 Linux kernel 換到最新的 7.1 試試看？換到 Linux kernel 7.1 後，碰到的</p>



<h3 class="wp-block-heading">第一個問題是 Image 太大，Bootloader 預設的 memcpy 量不夠大</h3>



<p>Booloader memcpy 從 4MB 改到 6MB就可以解決</p>



<h3 class="wp-block-heading">第二個問題：&#8221;broken padding&#8221; </h3>



<p>用 `dd` 從舊 kernel 複製 initramfs，但新 kernel 會出現問題，必須用 `fakeroot` 重新打包一份新的 cpio image。 </p>



<h3 class="wp-block-heading">第三個問題：使用預設的 initramfs 開機時，無法進入 shell</h3>



<p>錯誤訊息如下</p>



<pre class="wp-block-preformatted">  [   40.383751]     TERM=linux<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  init started: BusyBox v1.36.0 (2023-05-16 20:02:22 CEST)<br />  starting pid 18, tty '': '/etc/init.d/rcS'<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  sh: waitpid: Function not implemented<br />  mkdir: can't create directory '/': Function not implemented<br />  mkdir: can't create directory '/': Function not implemented<br />  mount: mounting devpts on /dev/pts failed: No such file or directory<br />  mount: mounting tmpfs on /dev/shm failed: No such file or directory</pre>



<p>這個問題是，Linux kernel mainline 的 <strong>RISC-V 32-bit 是 &#8220;time64-only&#8221; 架構</strong>：它是在 y2038 之後才進入 kernel 的，所以「刻意」不提供那些使用 32-bit 時間的舊 syscall（wait4、gettimeofday……）。而舊的 initramfs 是舊架構的，因此呼叫就會出錯，這需要換成新的 rootfs 來解決。在我處理的時候，buildroot 已經可以產生這個方案，使用 uClibc-ng 函式庫就可以了。</p>



<h3 class="wp-block-heading">第四個問題：&#8221;out of memory&#8221;</h3>



<pre class="wp-block-preformatted"><br />  [   47.660665] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 ]---<br />  sh: out of memory<br />   out of memory</pre>



<p>本來以為是 bFLT 的 heap/stack 不夠，所以把 stack 從 16KB 改為 1MB——結果沒用。最後發現這個問題和第六個問題是一樣的，本質上是 malloc 的問題。</p>



<h3 class="wp-block-heading">第五個問題：解完以上的問題之後，還是沒進到 shell，但是也沒有錯誤訊息。</h3>



<p>因為大部分都是 AI 解的，所以這邊 AI 也寫了一個程式，不過編譯的時候沒加 `-fPIC`，對 nommu 的 flat binary 來說，程式被載到記憶體的任意位置，所有位址都得是「位置無關」的。non-PIC 的程式用絕對位址（`lui aX, 0xNNN`）去抓字串或全域變數。這件事我知道，但是不常碰到，也很難意會到。光這個 Bug 就解了十輪左右，Claude 還想繼續解，但是我覺得應該要換個思路。</p>



<p>最後是自己去找了 mini-rv32ima，請 AI 分析差異在哪邊，AI 分析的同時還用了 <strong>qemu</strong> 直接執行程式（哎呀，我怎麼沒想到）。Claude 用了 qemu 後速度就快多了，很快就找到問題是在 <strong>-fPIC</strong>。</p>



<h3 class="wp-block-heading">第六個問題：<strong>malloc 在 nommu 上回 NULL</strong></h3>



<p>直接 mmap 一塊記憶體 → 成功；但 malloc 任何大小 → 都回傳 NULL。把 uClibc 改成 MALLOC_SIMPLE（純 mmap、為小系統設計的實作）就可以了。</p>



<p>雖然中間 claude 走錯很多次路，都需要人為校正回來，尤其是 -fPIC 這件事，我也沒意會到，只是覺得應該不會這樣複雜，所以試著要走別的路。這種經驗性的問題 Claude 是無法即時察覺的。或許 YOLO mode 可能可以最終也取得成本，但是這中間應該還要多燒更多的 tokens 達到目地，例如也有可能 AI 解不掉就生氣重寫一個 shell 或是大改 Linux kernel 之類的。</p>



<p>不過跟 AI debug 的過程還頗有趣的，想法和解題思路很像我會做的事，可能最終我也會走到這邊，但是花的時間會多非常非常多，畢竟以前就幹過類似的事情，只能說青春不值錢啊。以前和現在最大的差別是，有了 AI agents，我應該沒這個耐心自己解題，而是用 supervisor 的角度去解決問題。其實電腦科技發展一直是節省大家時間的，只是效果不會像 AI agents 這麼明顯，像是 assembly 到 C，或是第一次有了 database，dbase 大行其道，perl/php/甚至是 python 對 C/C++ 的衝擊。不過問題還是在於，會去研究底層的人會愈來愈少，但是未來可能會有更多新的不同的工具。但是這也沒關係，有需求就是有人會去弄的（或是花錢找人弄）。就像現在 assembly 很少人會寫，要用到的時候再寫個一點，但是我小時候，大家都要學上一些 assembly，望向我用 Microsoft ASM 寫 editor 的經歷，雖然曾經寫過，但是現在要不要學做 CPU，我也不太想碰 assembly 了。</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/06/19/6546/kianv-risc-v-linux-7-1-ulinux/">KianV Risc-V + Linux 7.1 uLinux</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2026/06/19/6546/kianv-risc-v-linux-7-1-ulinux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Run verilog Program on Lattice ECP5 Versa with OpenSource Tools</title>
		<link>https://richliu.com/2025/10/11/6424/run-verilog-program-on-lattice-ecp5-versa-with-opensource-tools/</link>
					<comments>https://richliu.com/2025/10/11/6424/run-verilog-program-on-lattice-ecp5-versa-with-opensource-tools/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Sat, 11 Oct 2025 15:37:56 +0000</pubDate>
				<category><![CDATA[IC Design]]></category>
		<category><![CDATA[RiscV]]></category>
		<category><![CDATA[ECP5]]></category>
		<category><![CDATA[FPGA]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6424</guid>

					<description><![CDATA[<p>其實也不是我願意這樣做，Lattice Diamond 明明支援我手上的 FPGA ，實際上就是找不到我這一塊 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2025/10/11/6424/run-verilog-program-on-lattice-ecp5-versa-with-opensource-tools/">Run verilog Program on Lattice ECP5 Versa with OpenSource Tools</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>其實也不是我願意這樣做，Lattice Diamond 明明支援我手上的 FPGA ，實際上就是找不到我這一塊 ECP5 Versa Board ，IC 型是 LFE5UM-45F ，而 Lattice Diamond 只支援 LEF5U-45F 。</p>



<p>所以只能用之前的 Open Source 開發環境編 Verilog 程式。首先請參照<a href="https://richliu.com/2025/08/27/6391/build-risc-v-on-ubuntu-linux/">Build Risc-V on Ubuntu Linux</a>設定開發環境</p>



<span id="more-6424"></span>



<p>最難的部份是找到 FPGA 的 clock input pin ，每一家 LLM 給的值都是錯的。實際上就是 User Manual 以下這段，不過我找到是從 litex-board 抓出來才知道原來是這一段，給個 table 啊，這文件不行，其它的 LED dip switch 都給了，clock 不給.</p>



<pre class="wp-block-preformatted">An on-board 100 MHz LVDS oscillator is provided for general purpose use. This clock source is connected to differential inputs P3 and P4 and must be used as LVDS inputs to the FPGA. This pin pair also provides optimal interface to the FPGA PLL for customized use.</pre>



<p>P3 and P4 pin 利用 LVDS 當 input. 這樣就可以寫 lpf 檔案，只能能抓出 clk ，而且知道FPGA ball number 要跟 verilog 對應。這樣就可以將LED 也抓進來了<br />而且看起來目前 FPGA 主要就是靠這兩根 pin 做 clk  輸入，100Mhz，如果是當 PCIe device 時也可以從 PCIe 那邊接 PCIe 的 clock 進來</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1636" height="466" src="https://richliu.com/wp-content/uploads/2025/10/image.png" alt="" class="wp-image-6425" srcset="https://richliu.com/wp-content/uploads/2025/10/image.png 1636w, https://richliu.com/wp-content/uploads/2025/10/image-600x171.png 600w, https://richliu.com/wp-content/uploads/2025/10/image-768x219.png 768w, https://richliu.com/wp-content/uploads/2025/10/image-1536x438.png 1536w, https://richliu.com/wp-content/uploads/2025/10/image-816x232.png 816w" sizes="(max-width: 1636px) 100vw, 1636px" /></figure>



<p>接下來我們就可以編 mapping file ，像是 ecp5evn.lpf 內容如下</p>



<pre class="wp-block-preformatted">LOCATE COMP "clk100" SITE "P3";<br />IOBUF PORT "clk100" IO_TYPE=LVDS;<br /><br /><br />LOCATE COMP "rst" SITE "H2";<br />IOBUF PORT "rst" IO_TYPE=LVCMOS33 PULLMODE=DOWN;<br /><br /># 將 Verilog 中的 "led" port 定位到 FPGA 的 LED output<br />LOCATE COMP "led[0]" SITE "F16";<br />IOBUF PORT "led[0]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[1]" SITE "E17";<br />IOBUF PORT "led[1]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[2]" SITE "F18";<br />IOBUF PORT "led[2]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[3]" SITE "F17";<br />IOBUF PORT "led[3]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[4]" SITE "E18";<br />IOBUF PORT "led[4]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[5]" SITE "D18";<br />IOBUF PORT "led[5]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[6]" SITE "D17";<br />IOBUF PORT "led[6]" IO_TYPE=LVCMOS33;<br />LOCATE COMP "led[7]" SITE "E16";<br />IOBUF PORT "led[7]" IO_TYPE=LVCMOS33;<br /></pre>



<p>然後寫一個簡單的 verilog 程式驗證我們的 code 是不是對的，像是一顆簡單的 CPU，然後寫了一個簡單的程式計算 1+10 </p>



<pre class="wp-block-code"><code>module aCPU (
    input  clk,   
    input  rst,
    output reg &#91;7:0] led,    // LED output
    output reg &#91;7:0] debug_led    // LED output
);
    // command
    parameter OP_NOP = 4'b0000   ;
    parameter OP_LI  = 4'b0001   ;
    parameter OP_ADD = 4'b0010   ;
    parameter OP_ADDI= 4'b0011   ; // copy s_reg + imm &#91;1:0] reg to d_reg
    parameter OP_BNER0 = 4'b0100   ;
    parameter OP_OUT = 4'b0101   ;
    parameter OP_HALT = 4'b0110   ;
    reg &#91;3:0] pc;
    reg &#91;7:0] register &#91;0:3];
    reg &#91;15:0] ir;   // ir = 指令暫存

    wire &#91;3:0] opcode /* verilator public */ = ir&#91;15:12];
    wire &#91;1:0] s_reg  = ir&#91;11:10];
    wire &#91;1:0] d_reg  = ir&#91;9:8];
    wire &#91;7:0] value  = ir&#91;7:0];

    reg &#91;15:0] program_memory &#91;0:15];


    // 初始化程式記憶體
    initial begin
        // 程式: 計算 1 + 10 並輸出
        program_memory&#91;0] = {OP_LI, 2'b00, 2'b00, 8'd1};    // LI only load to d_REG. s_reg no work
        program_memory&#91;1] = {OP_LI, 2'b01, 2'b01, 8'd11};   //
        program_memory&#91;2] = {OP_ADDI, 2'b10, 2'b10, 8'b0000}; // R3 = R2 + IMM
        program_memory&#91;3] = {OP_ADD, 2'b00, 2'b00, 8'b0001}; // R2 = R0 + IMM => R0
        program_memory&#91;4] = {OP_BNER0, 2'b00, 2'b01,8'b00000010}; // R0 跟 R1 比若不相同跳到 2
        program_memory&#91;5] = {OP_OUT,  2'b10, 2'b00, 8'b00000000}; // 輸出 s_reg to serial
        program_memory&#91;6] = {OP_HALT, 2'b10, 2'b01, 8'b00000000};     // 停止
    end
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            pc &lt;= 0;
            register&#91;0] &lt;= 0;
            register&#91;1] &lt;= 0;
            register&#91;2] &lt;= 0;
            register&#91;3] &lt;= 0;
            led &lt;= 8'b11111111;
            debug_led &lt;= 8'b11111111;
        end
        else begin
            pc &lt;= pc + 1;
            ir &lt;= program_memory&#91;pc];
            // $display("pc&#91;%d] ir:%x reg&#91;0]:%d reg&#91;1]:%d reg&#91;2]:%d value: %x \n", pc, ir, register&#91;0], register&#91;1], register&#91;2], value);
            case (opcode)
                 OP_NOP: begin
                 end
                 OP_LI: begin
                    register&#91;s_reg] &lt;= value;
                 end
                 OP_ADD: begin
                    register&#91;d_reg] &lt;= register&#91;s_reg] + value;
                 end
                 OP_ADDI: begin
                    register&#91;d_reg] &lt;= register&#91;s_reg] + register&#91;value&#91;1:0]];
                 end
                 OP_BNER0: begin
                    if (register&#91;s_reg] != register&#91;d_reg]) begin
                        pc &lt;= value&#91;3:0];
                    end
                 end
                 OP_OUT: begin
                    led &lt;= register&#91;s_reg];
                 end
                 OP_HALT: begin
                    pc &lt;= pc - 1;
                 end
                 default: begin
                    // $display("Error No this command OP_CODE: %x ir: %x ", opcode, ir);
                 end
            endcase
        end
    end
endmodule</code></pre>



<p>當然為了這個程式就需要寫一個 test bench 檔案，就叫 ${PRJNAME}_tb.cpp <br />這不僅僅是當 test bench ，後來在弄的過程才知道可以靠 $display 顯示電路內的狀態，比幻想簡單太多了</p>



<pre class="wp-block-code"><code>#include &lt;stdio.h>
#include &lt;stdlib.h>
#include &lt;assert.h>
#include "VsCPU.h"
#include "verilated.h"

#include "verilated_vcd_c.h"

int main (int argc, char** argv, char** env){

    VerilatedContext* contextp = new VerilatedContext;
    contextp->commandArgs(argc, argv);
    VsCPU* top = new VsCPU{contextp};

    VerilatedVcdC* tfp = new VerilatedVcdC;
    contextp->traceEverOn(true); // open trace function
    top->trace(tfp, 99);
    tfp->open("wave.vcd");
    int clk = 0;

    int cycles = 0;
    while (!contextp->gotFinish() &amp;&amp; (cycles &lt; 100) ) {
      clk = !clk;
      top->clk100 = clk;
      top->eval();
      tfp->dump(contextp->time()); // dump wave
      contextp->timeInc(1); // move time to next clock

      if (cycles > 50) {
          // 檢查 LED 輸出是否為預期值 (1 + 10 = 11)
          if (top->led == (u_int8_t) ~0xc8) {
              printf("SUCCESS: 1 + 10 = %d\n", top->led);
              break;
          }
      }
      cycles++;
      if (cycles >= 99) {
          printf("TIMEOUT: Expected result not reached\n");
      }

    }
    //
    if (tfp) {
        tfp->close();
        delete tfp;
    }
    delete top;
    return 0;
}
</code></pre>



<p>然後撰寫一個 Makefile ，可以直接 Compile Code 變 bitstream 而且可以上傳到 FPGA 上.</p>



<pre class="wp-block-preformatted">DEVICE = um-45k<br />PACKAGE = CABGA381<br /><br />PRJNAME=aCPU<br /><br />all: ${PRJNAME}.bit<br /><br />${PRJNAME}.json: ${PRJNAME}.v<br />        yosys -p "synth_ecp5 -json ${PRJNAME}.json" ${PRJNAME}.v<br /><br />${PRJNAME}_out.config: ${PRJNAME}.json<br />        nextpnr-ecp5 --$(DEVICE) --package $(PACKAGE) --json ${PRJNAME}.json \<br />        --lpf ecp5evn.lpf --textcfg ${PRJNAME}_out.config<br /><br />${PRJNAME}.bit: ${PRJNAME}_out.config<br />        ecppack --svf ${PRJNAME}.svf ${PRJNAME}_out.config ${PRJNAME}.bit<br /><br />sim:<br />        verilator -Wall --cc --exe --build --trace ${PRJNAME}.v ${PRJNAME}_tb.cpp<br /><br />program:<br />        openFPGALoader -b ecp5_evn ${PRJNAME}.bit<br /><br />clean:<br />        rm -f *.json *.config *.bit *.svf</pre>



<p>make sim 之後執行 ./obj_dir/VaCPU 就可以看到程式輸出的結果，果然還是印出來比較簡單 debug</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1174" height="769" src="https://richliu.com/wp-content/uploads/2025/10/image-1.png" alt="" class="wp-image-6426" srcset="https://richliu.com/wp-content/uploads/2025/10/image-1.png 1174w, https://richliu.com/wp-content/uploads/2025/10/image-1-600x393.png 600w, https://richliu.com/wp-content/uploads/2025/10/image-1-768x503.png 768w, https://richliu.com/wp-content/uploads/2025/10/image-1-816x535.png 816w" sizes="(max-width: 1174px) 100vw, 1174px" /></figure>



<p>同時也會產生 wave.vcd  這時可以用 gtkwave 看波形</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1236" height="834" src="https://richliu.com/wp-content/uploads/2025/10/image-2.png" alt="" class="wp-image-6427" srcset="https://richliu.com/wp-content/uploads/2025/10/image-2.png 1236w, https://richliu.com/wp-content/uploads/2025/10/image-2-600x405.png 600w, https://richliu.com/wp-content/uploads/2025/10/image-2-768x518.png 768w, https://richliu.com/wp-content/uploads/2025/10/image-2-816x551.png 816w" sizes="auto, (max-width: 1236px) 100vw, 1236px" /></figure>



<p>make program 之後就可以燒到 FPGA 板子上啦，輸出的燈號是反向的</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1280" height="960" src="https://richliu.com/wp-content/uploads/2025/10/image-3.png" alt="" class="wp-image-6428" srcset="https://richliu.com/wp-content/uploads/2025/10/image-3.png 1280w, https://richliu.com/wp-content/uploads/2025/10/image-3-600x450.png 600w, https://richliu.com/wp-content/uploads/2025/10/image-3-768x576.png 768w, https://richliu.com/wp-content/uploads/2025/10/image-3-816x612.png 816w" sizes="auto, (max-width: 1280px) 100vw, 1280px" /></figure>
<p>The post <a rel="nofollow" href="https://richliu.com/2025/10/11/6424/run-verilog-program-on-lattice-ecp5-versa-with-opensource-tools/">Run verilog Program on Lattice ECP5 Versa with OpenSource Tools</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2025/10/11/6424/run-verilog-program-on-lattice-ecp5-versa-with-opensource-tools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Running Risc-V Linux on Lattice Versa ECP5 EVB</title>
		<link>https://richliu.com/2025/09/21/6411/running-risc-v-linux-on-lattice-versa-ecp5-evb/</link>
					<comments>https://richliu.com/2025/09/21/6411/running-risc-v-linux-on-lattice-versa-ecp5-evb/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Sun, 21 Sep 2025 06:50:27 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[IC Design]]></category>
		<category><![CDATA[RiscV]]></category>
		<category><![CDATA[ECP5]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Linux-on-lite-vexriscv]]></category>
		<category><![CDATA[LiteX]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6411</guid>

					<description><![CDATA[<p>大部份的環境都要用上一篇(Build Risc-V on Ubuntu Linux)相同的環境，但是其實還有更 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2025/09/21/6411/running-risc-v-linux-on-lattice-versa-ecp5-evb/">Running Risc-V Linux on Lattice Versa ECP5 EVB</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>大部份的環境都要用上一篇(<a href="https://richliu.com/2025/08/27/6391/build-risc-v-on-ubuntu-linux/">Build Risc-V on Ubuntu Linux</a>)相同的環境，但是其實還有更多的問題，中間也踩了不少地雷，還好都不算難解的問題</p>



<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#lattice-versa-evb-board-晶片型號不同">Lattice Versa EVB Board 晶片型號不同</a></li><li><a href="#連接上-evb-board">連接上 EVB Board</a></li><li><a href="#燒錄-bitstream-到板子上">燒錄 bitstream 到板子上</a></li><li><a href="#設定-udev">設定 udev</a></li></ul></nav></div>



<span id="more-6411"></span>



<h3 class="wp-block-heading" id="lattice-versa-evb-board-晶片型號不同">Lattice Versa EVB Board 晶片型號不同</h3>



<p>這個是最主要的問題，因為文件並不會提到這件事，都會用 versa_ecp5 帶過，但是實際上 versa_ecp5 是使用 LFE5UM5G-85F 的晶片，晶片比較新，邏輯閘數也比較多。一般市面上賣的 versa_ecp5 是 LFE5UM5G-45F，一片約在一萬元左右。<br />我從淘寶看到一塊比較便宜的 LFE5UM5G-45F ，結果買回來後是 LFE5UM-45F ，沒有 5G。查詢網路上的資料，大概只差在 SEDERS 最高頻可以到 5G ，還有速度比較快。</p>



<p>但是 LiteX default versa_ecp5 是預設用 LFE5UM5G-85F ，在燒錄時就會失敗，ID 不一樣</p>



<p>此時我們就要重編一次 Linux-on-litex-vexriscv ，加上 device 的參數，這樣就可以了</p>



<pre class="wp-block-code"><code>./make.py --device LFE5UM --board=versa_ecp5 --cpu-count=1 --build</code></pre>



<p>編出來的 bitstream 和 fpga hardware 不同的錯誤訊息，可以看到 hardware id 不一樣</p>



<pre class="wp-block-preformatted">$ openFPGALoader -b ecp5_evn versa_ecp5.bit<br />empty<br />Jtag frequency : requested 6.00MHz    -&gt; real 6.00MHz<br />Open file: DONE<br />b3bdffff<br />Parse file: DONE<br />mismatch between target's idcode and bitstream idcode<br />        bitstream has <strong>0x81112043 </strong>hardware requires <strong>0x01112043</strong><br />Error: Failed to program FPGA: std::exception</pre>



<h3 class="wp-block-heading" id="連接上-evb-board">連接上 EVB Board </h3>



<p>EVB Board 應該支援 ethernet load ，但是我還沒試出來，就當 TBD 吧，看設定檔內 ethernet 是可以用的</p>



<p>EVB Board 上的 FT2232H 支援 JTAG 和 Serial Port ，Linux kernel 的 image 可以從 serial port load，不過速度好慢啊</p>



<p>我之前用 Diamond programmer 要燒錄編出來的 bitstream file ，但是因為 id mismatch 的關係所以燒不上去，所以我最後是找了一台乾淨的 Linux 直接接 EVB Board 的 USB （要注意，這塊版子的 USB Port 是 mini-USB ，如果沒附線要有支援 mini-USB 的線），就這樣找到最後才發現根本型號不一樣，所以這篇就不會提到 Diamond programmer</p>



<p>記得接上之前要將 FTDI 的J50跳線改成下圖這樣，要跳過 iSPclock </p>



<p>（原文 <strong>Note</strong>: If you are using a Versa board, you will need to change J50 to bypass the iSPclock. Re-arrange the jumpers to connect pins 1-2 and 3-5 (leaving one jumper spare). See p19 of the Versa Board user guide.）</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="699" height="627" src="https://richliu.com/wp-content/uploads/2025/09/image.png" alt="" class="wp-image-6412" srcset="https://richliu.com/wp-content/uploads/2025/09/image.png 699w, https://richliu.com/wp-content/uploads/2025/09/image-600x538.png 600w" sizes="auto, (max-width: 699px) 100vw, 699px" /></figure>



<p>接上去之後，上電之後，Linux 下會出現 /dev/ttyUSB0 是 JTAG 的介面，/dev/ttyUSB1 是 serial port 的介面</p>



<p>在另一個視窗先執行 litex_term（記得在 venv 環境下執行）</p>



<pre class="wp-block-code"><code>litex_term --images=images/boot.json /dev/ttyUSB1</code></pre>



<h3 class="wp-block-heading" id="燒錄-bitstream-到板子上">燒錄 bitstream 到板子上</h3>



<p>最後一步就是燒錄上去了，我是用 OpenFPGAloader ，以下是安裝步驟</p>



<pre class="wp-block-code"><code>sudo apt install -y  libftdi1-dev

cd /nvme/cpu
git clone https://github.com/trabucayre/openFPGALoader
cd openFPGALoader
mkdir -p build
cd build
cmake ../
make -j `nproc`
sudo make install </code></pre>



<p>然後到 linux-on-litex-vexriscv 下用 OpenFPGAloader 暫時 load bitstream 上去，這速度很快，這樣就不用燒上去了</p>



<pre class="wp-block-code"><code>cd /nvme/cpu/linux-on-litex-vexriscv/build/versa_ecp5/gateware
$ openFPGALoader -b ecp5_evn versa_ecp5.bit
empty
Jtag frequency : requested 6.00MHz    -&gt; real 6.00MHz
Open file: DONE
b3bdffff
Parse file: DONE
Enable configuration: DONE
SRAM erase: DONE
Loading: &#91;==================================================] 100.00%
Done
Disable configuration: DONE</code></pre>



<p>如果順利，可以在剛剛執行 litex_term 上看到 load image 訊息<br />如果用的是上一篇文章內提到的先下載好 RiscV 的 Linux image 和 rootfs ，就可以看到 Linux boot 了</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="943" height="927" src="https://richliu.com/wp-content/uploads/2025/09/image-1.png" alt="" class="wp-image-6413" srcset="https://richliu.com/wp-content/uploads/2025/09/image-1.png 943w, https://richliu.com/wp-content/uploads/2025/09/image-1-600x590.png 600w, https://richliu.com/wp-content/uploads/2025/09/image-1-768x755.png 768w, https://richliu.com/wp-content/uploads/2025/09/image-1-88x88.png 88w, https://richliu.com/wp-content/uploads/2025/09/image-1-816x802.png 816w" sizes="auto, (max-width: 943px) 100vw, 943px" /></figure>



<p>這年代可以自己編一顆 CPU 跑起來也真的是很有趣</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1353" height="927" src="https://richliu.com/wp-content/uploads/2025/09/image-2.png" alt="" class="wp-image-6414" srcset="https://richliu.com/wp-content/uploads/2025/09/image-2.png 1353w, https://richliu.com/wp-content/uploads/2025/09/image-2-600x411.png 600w, https://richliu.com/wp-content/uploads/2025/09/image-2-768x526.png 768w, https://richliu.com/wp-content/uploads/2025/09/image-2-816x559.png 816w" sizes="auto, (max-width: 1353px) 100vw, 1353px" /></figure>



<p>以下未完成，待續</p>



<h3 class="wp-block-heading" id="設定-udev">設定 udev</h3>



<p>這塊版子看起來要設定過 udev 才能被 LiteX 抓到，首先新增檔案 /etc/udev/rules.d/99-ftdi.rules<br />內容如下，記得 GROUP=換成 Linux login 帳號</p>



<pre class="wp-block-preformatted">SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0660", GROUP="使用者名稱"</pre>



<p>然後執行以下命令之後再重新上電即可</p>



<pre class="wp-block-code"><code>sudo udevadm control --reload-rules
sudo udevadm trigger</code></pre>



<p>這個命令也可以像 OpenFPGAloader 一樣將 bitstream load 到 FPGA 上</p>



<pre class="wp-block-code"><code>./make.py --device LFE5UM --board=versa_ecp5 --cpu-count=1 --load </code></pre>



<p>45F Gate count 夠放二顆 CPU ，所以可以跑 SMP</p>



<pre class="wp-block-code"><code>./make.py --device LFE5UM --board=versa_ecp5 --cpu-count=2 --build
./make.py --device LFE5UM --board=versa_ecp5 --cpu-count=2 --load </code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1299" height="1033" src="https://richliu.com/wp-content/uploads/2025/09/image-3.png" alt="" class="wp-image-6418" srcset="https://richliu.com/wp-content/uploads/2025/09/image-3.png 1299w, https://richliu.com/wp-content/uploads/2025/09/image-3-600x477.png 600w, https://richliu.com/wp-content/uploads/2025/09/image-3-768x611.png 768w, https://richliu.com/wp-content/uploads/2025/09/image-3-816x649.png 816w" sizes="auto, (max-width: 1299px) 100vw, 1299px" /></figure>
<p>The post <a rel="nofollow" href="https://richliu.com/2025/09/21/6411/running-risc-v-linux-on-lattice-versa-ecp5-evb/">Running Risc-V Linux on Lattice Versa ECP5 EVB</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2025/09/21/6411/running-risc-v-linux-on-lattice-versa-ecp5-evb/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Altera FPGA 簡體中文教學</title>
		<link>https://richliu.com/2011/01/21/1014/altera-fpga-%e7%b0%a1%e9%ab%94%e4%b8%ad%e6%96%87%e6%95%99%e5%ad%b8/</link>
					<comments>https://richliu.com/2011/01/21/1014/altera-fpga-%e7%b0%a1%e9%ab%94%e4%b8%ad%e6%96%87%e6%95%99%e5%ad%b8/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Fri, 21 Jan 2011 03:57:01 +0000</pubDate>
				<category><![CDATA[IC Design]]></category>
		<category><![CDATA[Altera]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tranning]]></category>
		<category><![CDATA[教學]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1014</guid>

					<description><![CDATA[<p>Altera 簡體中文教學 我目前正在學習 Altera FPGA, 發現到這個簡體中文教學網站不錯, 講解的 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/01/21/1014/altera-fpga-%e7%b0%a1%e9%ab%94%e4%b8%ad%e6%96%87%e6%95%99%e5%ad%b8/">Altera FPGA 簡體中文教學</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="http://www.altera.com.cn/education/courses/online-courses.html?f=hp&amp;k=g1" target="_blank" rel="noopener">Altera 簡體中文教學</a></p>
<p>我目前正在學習 Altera FPGA, 發現到這個簡體中文教學網站不錯, 講解的東西也很詳細, 線上版是從 webex streaming. 也可以離線閱讀. 離線閱讀時使用 Flash 格式, 但是非常方便, 就像是翻 PowerPoint 時, 有人替你講解.</p>
<p>Ubuntu 10.04 下看也沒有問題.</p>
<p>總之, 是非常好的入門學習文件</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/01/21/1014/altera-fpga-%e7%b0%a1%e9%ab%94%e4%b8%ad%e6%96%87%e6%95%99%e5%ad%b8/">Altera FPGA 簡體中文教學</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2011/01/21/1014/altera-fpga-%e7%b0%a1%e9%ab%94%e4%b8%ad%e6%96%87%e6%95%99%e5%ad%b8/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
