关注 望森FPGA 查看更多FPGA资讯
这是望森的第 17 期分享
作者 | 望森
来源 | 望森FPGA
目录
1 Lemmings 1
2 Lemmings 2
3 Lemmings 3
4 Lemmings 4
5 One-hot FSM | 独热 FSM
6 PS/2 packet parser | PS/2 数据包解析器
7 PS/2 packet parser anddatapath | PS/2 数据包解析器和数据路径
本文中的代码都能够正常运行,请放心食用😋~
练习的官方网站是:https://hdlbits.01xz.net/
注:作者将每个练习的知识点都放在了题目和答案之后
1 Lemmings 1
题目:
游戏《旅鼠》涉及的动物大脑相当简单。非常简单,我们将使用有限状态机对其进行建模。
在《旅鼠》的 2D 世界中,旅鼠可以处于两种状态之一:向左行走或向右行走。如果撞到障碍物,它会改变方向。具体来说,如果旅鼠左侧受到撞击,它会向右行走。如果右侧受到撞击,它会向左行走。如果两侧同时受到撞击,它仍会改变方向。
实现一个 Moore 状态机,该状态机具有两个状态、两个输入和一个输出,可以对此行为进行建模。
答案:
我的答案:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
// parameter LEFT=0, RIGHT=1, ...
reg state, next_state;
parameter LEFT=1'b0, RIGHT=1'b1;
wire LEFT2LEFT,LEFT2RIGHT,RIGHT2RIGHT,RIGHT2LEFT;
always @(posedge clk or posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
LEFT : begin
if (LEFT2LEFT)begin
next_state = LEFT;
end
else if (LEFT2RIGHT)begin
next_state = RIGHT;
end
end
RIGHT : begin
if (RIGHT2RIGHT)begin
next_state = RIGHT;
end
else if (RIGHT2LEFT)begin
next_state = LEFT;
end
end
default next_state = state;
endcase
end
assign LEFT2LEFT = !bump_left;
assign LEFT2RIGHT = bump_left;
assign RIGHT2RIGHT = !bump_right;
assign RIGHT2LEFT = bump_right;
// Output logic
// assign out = (state == ...);
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
参考答案:
module top_module (
input clk,
input areset,
input bump_left,
input bump_right,
output walk_left,
output walk_right
);
// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
// It doesn't really matter what assignment is used, as long as they're unique.
parameter WL=0, WR=1;
reg state;
reg next;
// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always@(*) begin
case (state)
WL: next = bump_left ? WR : WL;
WR: next = bump_right ? WL : WR;
endcase
end
// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always @(posedge clk, posedge areset) begin
if (areset) state <= WL;
else state <= next;
end
// Combinational output logic. In this problem, an assign statement are the simplest.
// In more complex circuits, a combinational always block may be more suitable.
assign walk_left = (state==WL);
assign walk_right = (state==WR);
endmodule
知识点:
提示:
2 Lemmings 2
题目:
除了左右行走外,如果脚下的地面消失,旅鼠还会摔倒(大概会发出“啊啊啊”的声音)。
除了左右行走和被撞时改变方向外,当地面 = 0 时,旅鼠还会摔倒并发出“啊啊啊”的声音。当地面重新出现(地面 = 1 时),旅鼠会继续沿摔倒前的方向行走。摔倒时被撞不会影响行走方向,在地面消失(但尚未摔倒)的同一周期内被撞,或者在摔倒时地面重新出现,也不会影响行走方向。
构建一个有限状态机来模拟此行为。
答案:
1.状态转换图
2.代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
// parameter LEFT=0, RIGHT=1, ...
reg [1:0] state, next_state;
parameter LEFT=2'd0, RIGHT=2'd1,FALL_LEFT=2'd2,FALL_RIGHT=2'd3;
wire LEFT2LEFT,LEFT2RIGHT,LEFT2FALL_LEFT,RIGHT2RIGHT,RIGHT2LEFT,RIGHT2FALL_RIGHT
,FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT;
always @(posedge clk or posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
LEFT : begin
if (LEFT2LEFT)begin
next_state = LEFT;
end
else if (LEFT2RIGHT)begin
next_state = RIGHT;
end
else if (LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
end
RIGHT : begin
if (RIGHT2RIGHT)begin
next_state = RIGHT;
end
else if (RIGHT2LEFT)begin
next_state = LEFT;
end
else if (RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
end
FALL_LEFT : begin
if (FALL_LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
else if (FALL_LEFT2LEFT)begin
next_state = LEFT;
end
end
FALL_RIGHT : begin
if (FALL_RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
else if (FALL_RIGHT2RIGHT)begin
next_state = RIGHT;
end
end
default next_state = state;
endcase
end
assign LEFT2LEFT = !bump_left && ground;
assign LEFT2RIGHT = bump_left && ground;
assign LEFT2FALL_LEFT = !ground;
assign RIGHT2RIGHT = !bump_right && ground;
assign RIGHT2LEFT = bump_right && ground;
assign RIGHT2FALL_RIGHT = !ground;
assign FALL_LEFT2FALL_LEFT = !ground;
assign FALL_LEFT2LEFT = ground;
assign FALL_RIGHT2FALL_RIGHT = !ground;
assign FALL_RIGHT2RIGHT = ground;
// Output logic
// assign out = (state == ...);
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_LEFT) || (state == FALL_RIGHT);
endmodule
知识点:
提示:
3 Lemmings 3
题目:
除了行走和跌倒,有时还可以命令旅鼠做一些有用的事情,比如挖掘(当 dig=1 时,它会开始挖掘)。如果旅鼠当前正在地面上行走( ground=1 且没有跌倒),它可以挖掘,并会继续挖掘直到到达另一侧( ground=0 )。此时,由于没有地面,它会跌倒(aaah!),然后再次接触地面后继续沿其原始方向行走。与跌倒一样,在挖掘时受到撞击不会产生任何影响,并且在跌倒或没有地面时被告知挖掘会被忽略。
(换句话说,行走的旅鼠可以跌倒、挖掘或切换方向。如果满足这些条件中的多个条件,则跌倒的优先级高于挖掘,而挖掘的优先级高于切换方向。)
扩展您的有限状态机以模拟此行为。
答案:
1.状态转换图
2.代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
reg [2:0] state, next_state;
parameter LEFT=3'd0, RIGHT=3'd1,DIG_LEFT=3'd2,DIG_RIGHT=3'd3,FALL_LEFT=3'd4,FALL_RIGHT=3'd5;
wire LEFT2LEFT,LEFT2RIGHT,LEFT2DIG_LEFT,LEFT2FALL_LEFT,
RIGHT2RIGHT,RIGHT2LEFT,RIGHT2DIG_RIGHT,RIGHT2FALL_RIGHT,
DIG_LEFT2FALL_LEFT,DIG_LEFT2DIG_LEFT,
DIG_RIGHT2FALL_RIGHT,DIG_RIGHT2DIG_RIGHT,
FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,
FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT;
always @(posedge clk or posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
LEFT : begin
if (LEFT2LEFT)begin
next_state = LEFT;
end
else if (LEFT2RIGHT)begin
next_state = RIGHT;
end
else if (LEFT2DIG_LEFT)begin
next_state = DIG_LEFT;
end
else if (LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
end
RIGHT : begin
if (RIGHT2RIGHT)begin
next_state = RIGHT;
end
else if (RIGHT2LEFT)begin
next_state = LEFT;
end
else if (RIGHT2DIG_RIGHT)begin
next_state = DIG_RIGHT;
end
else if (RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
end
DIG_LEFT : begin
if (DIG_LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
else if (DIG_LEFT2DIG_LEFT)begin
next_state = DIG_LEFT;
end
end
DIG_RIGHT : begin
if (DIG_RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
else if (DIG_RIGHT2DIG_RIGHT)begin
next_state = DIG_RIGHT;
end
end
FALL_LEFT : begin
if (FALL_LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
else if (FALL_LEFT2LEFT)begin
next_state = LEFT;
end
end
FALL_RIGHT : begin
if (FALL_RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
else if (FALL_RIGHT2RIGHT)begin
next_state = RIGHT;
end
end
default next_state = LEFT;
endcase
end
/*bump_left,bump_right,ground,dig,*/
assign LEFT2LEFT = !bump_left && ground && !dig;
assign LEFT2RIGHT = bump_left && ground && !dig;
assign LEFT2DIG_LEFT = ground && dig;
assign LEFT2FALL_LEFT = !ground;
assign RIGHT2RIGHT = !bump_right && ground && !dig;
assign RIGHT2LEFT = bump_right && ground && !dig;
assign RIGHT2DIG_RIGHT = ground && dig;
assign RIGHT2FALL_RIGHT = !ground;
assign DIG_LEFT2FALL_LEFT = !ground;
assign DIG_LEFT2DIG_LEFT = ground;
assign DIG_RIGHT2FALL_RIGHT = !ground;
assign DIG_RIGHT2DIG_RIGHT = ground ;
assign FALL_LEFT2FALL_LEFT = !ground;
assign FALL_LEFT2LEFT = ground;
assign FALL_RIGHT2FALL_RIGHT = !ground;
assign FALL_RIGHT2RIGHT = ground;
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_LEFT) || (state == FALL_RIGHT);
assign digging = (state == DIG_LEFT) || (state == DIG_RIGHT);
endmodule
知识点:
提示:
4 Lemmings 4
题目:
尽管旅鼠可以行走、跌倒和挖洞,但它们并非无懈可击。如果旅鼠跌倒时间过长,然后撞到地面,它就会 splatter 四分五裂。具体来说,如果旅鼠跌倒超过 20 个时钟周期,然后撞到地面,它就会四分五裂并停止行走、跌倒或挖洞(所有 4 个输出都变为 0),永远(或直到 FSM 重置)。旅鼠在撞到地面之前可以跌倒多远没有上限。旅鼠只有在撞到地面时才会四分五裂;它们不会在半空中四分五裂。
扩展您的有限状态机以模拟此行为。
跌倒 20 个周期是可以存活的:
跌落21次导致四分五裂:
答案:
1.状态转换图
2.代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
reg [2:0] state, next_state;
parameter LEFT=3'd0, RIGHT=3'd1,DIG_LEFT=3'd2,DIG_RIGHT=3'd3,
FALL_LEFT=3'd4,FALL_RIGHT=3'd5,SLATTER=3'd6;
reg [4:0] cnt_fall;
reg FALL_20clk;
wire LEFT2LEFT,LEFT2RIGHT,LEFT2DIG_LEFT,LEFT2FALL_LEFT,
RIGHT2RIGHT,RIGHT2LEFT,RIGHT2DIG_RIGHT,RIGHT2FALL_RIGHT,
DIG_LEFT2FALL_LEFT,DIG_LEFT2DIG_LEFT,
DIG_RIGHT2FALL_RIGHT,DIG_RIGHT2DIG_RIGHT,
FALL_LEFT2FALL_LEFT,FALL_LEFT2LEFT,FALL_LEFT2SLATTER,
FALL_RIGHT2FALL_RIGHT,FALL_RIGHT2RIGHT,FALL_RIGHT2SLATTER;
//FALL counter & 20clk flag
always @(posedge clk or posedge areset) begin
if(areset)begin
cnt_fall <= 5'd0;
end
else if(state == FALL_LEFT || state == FALL_RIGHT)begin
cnt_fall <= cnt_fall + 5'd1;
end
else begin
cnt_fall <= 5'd0;
end
end
always @(*) begin
if(areset)begin
FALL_20clk = 1'd0;
end
else if(cnt_fall > 5'd19)begin
FALL_20clk = 1'd1;
end
else begin
FALL_20clk = FALL_20clk;
end
end
always @(posedge clk or posedge areset) begin
if(areset)begin
state <= LEFT;
end
else begin
state <= next_state;
end
end
always @(*) begin
case(state)
LEFT : begin
if (LEFT2LEFT)begin
next_state = LEFT;
end
else if (LEFT2RIGHT)begin
next_state = RIGHT;
end
else if (LEFT2DIG_LEFT)begin
next_state = DIG_LEFT;
end
else if (LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
end
RIGHT : begin
if (RIGHT2RIGHT)begin
next_state = RIGHT;
end
else if (RIGHT2LEFT)begin
next_state = LEFT;
end
else if (RIGHT2DIG_RIGHT)begin
next_state = DIG_RIGHT;
end
else if (RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
end
DIG_LEFT : begin
if (DIG_LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
else if (DIG_LEFT2DIG_LEFT)begin
next_state = DIG_LEFT;
end
end
DIG_RIGHT : begin
if (DIG_RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
else if (DIG_RIGHT2DIG_RIGHT)begin
next_state = DIG_RIGHT;
end
end
FALL_LEFT : begin
if (FALL_LEFT2FALL_LEFT)begin
next_state = FALL_LEFT;
end
else if (FALL_LEFT2LEFT)begin
next_state = LEFT;
end
else if (FALL_LEFT2SLATTER)begin
next_state = SLATTER;
end
end
FALL_RIGHT : begin
if (FALL_RIGHT2FALL_RIGHT)begin
next_state = FALL_RIGHT;
end
else if (FALL_RIGHT2RIGHT)begin
next_state = RIGHT;
end
else if (FALL_RIGHT2SLATTER)begin
next_state = SLATTER;
end
end
SLATTER : begin
next_state = SLATTER;
end
default next_state = LEFT;
endcase
end
/*bump_left,bump_right,ground,dig,*/
assign LEFT2LEFT = !bump_left && ground && !dig;
assign LEFT2RIGHT = bump_left && ground && !dig;
assign LEFT2DIG_LEFT = ground && dig;
assign LEFT2FALL_LEFT = !ground;
assign RIGHT2RIGHT = !bump_right && ground && !dig;
assign RIGHT2LEFT = bump_right && ground && !dig;
assign RIGHT2DIG_RIGHT = ground && dig;
assign RIGHT2FALL_RIGHT = !ground;
assign DIG_LEFT2FALL_LEFT = !ground;
assign DIG_LEFT2DIG_LEFT = ground;
assign DIG_RIGHT2FALL_RIGHT = !ground;
assign DIG_RIGHT2DIG_RIGHT = ground ;
assign FALL_LEFT2FALL_LEFT = !ground;
assign FALL_LEFT2LEFT = ground && !FALL_20clk;
assign FALL_LEFT2SLATTER = ground && FALL_20clk;
assign FALL_RIGHT2FALL_RIGHT = !ground;
assign FALL_RIGHT2RIGHT = ground && !FALL_20clk;
assign FALL_RIGHT2SLATTER = ground && FALL_20clk;
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_LEFT) || (state == FALL_RIGHT);
assign digging = (state == DIG_LEFT) || (state == DIG_RIGHT);
endmodule
知识点:
提示:使用 FSM 来控制计数器,追踪 Lemming 下落的时间长度。
5 One-hot FSM | 独热 FSM
题目:
给定以下具有 1 个输入和 2 个输出的状态机:
假设此状态机使用独热编码,其中 state[0] 到 state[9] 分别对应于状态 S0 到 S9。除非另有说明,否则输出为零。
实现状态机的状态转换逻辑和输出逻辑部分(但不是状态触发器)。您将在 state[9:0] 中得到当前状态,并且必须生成 next_state[9:0] 和两个输出。通过检查得出逻辑方程,假设采用独热编码。(测试台将使用非独热输入进行测试,以确保您不会尝试执行更复杂的事情)。
提示:
通过查看状态转换图的入边,可以推导出独热状态转换逻辑的逻辑方程。
答案:
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2
);
parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4, S5 = 5, S6 = 6, S7 = 7, S8 = 8, S9 = 9 ;
assign next_state[S0] = (state[S0] & !in) | (state[S1] & !in) | (state[S2] & !in) | (state[S3] & !in) | (state[S4] & !in) |
(state[S7] & !in) | (state[S8] & !in) | (state[S9] & !in) ;
assign next_state[S1] = (state[S0] & in) | (state[S8] & in) | (state[S9] & in) ;
assign next_state[S2] = state[S1] & in ;
assign next_state[S3] = state[S2] & in ;
assign next_state[S4] = state[S3] & in ;
assign next_state[S5] = state[S4] & in ;
assign next_state[S6] = state[S5] & in ;
assign next_state[S7] = (state[S6] & in) | (state[S7] & in) ;
assign next_state[S8] = state[S5] & !in ;
assign next_state[S9] = state[S6] & !in ;
assign out1 = state[S8] | state[S9] ;
assign out2 = state[S7] | state[S9] ;
endmodule
6 PS/2 packet parser | PS/2 数据包解析器
题目:
PS/2 鼠标协议发送三个字节长的消息。但是,在连续的字节流中,消息的开始和结束位置并不明显。唯一的迹象是每个三字节消息的第一个字节始终具有 bit[3]=1(但其他两个字节的 bit[3] 可能为 1 或 0,具体取决于数据)。
我们想要一个有限状态机,当给定输入字节流时,它将搜索消息边界。我们将使用的算法是丢弃字节,直到我们看到 bit[3]=1 的字节。然后我们假设这是消息的第 1 个字节,并在收到所有 3 个字节(完成)后发出消息接收信号。
在成功接收每条消息的第三个字节后,FSM 应立即在循环中发出完成信号。
一些时序图用于解释所需行为
在无错误的情况下,每三个字节形成一条消息:
当发生错误时,搜索字节1:
请注意,这与 1xx 序列识别器不同。这里不允许重叠序列:
答案:
1.状态转换图
2.代码
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
reg [1:0] state, next_state;
parameter BYTE1=2'd0, BYTE2=2'd1, BYTE3=2'd2, DONE=2'd3;
wire BYTE12BYTE1,BYTE12BYTE2,DONE2BYTE1,DONE2BYTE2;
// State transition logic (combinational)
always @(posedge clk) begin
if(reset)begin
state <= BYTE1;
end
else begin
state <= next_state;
end
end
always @(*) begin
case(state)
BYTE1 : begin
if (BYTE12BYTE1)begin
next_state = BYTE1;
end
else if (BYTE12BYTE2)begin
next_state = BYTE2;
end
end
BYTE2 : begin
next_state = BYTE3;
end
BYTE3 : begin
next_state = DONE;
end
DONE : begin
if (DONE2BYTE1)begin
next_state = BYTE1;
end
else if (DONE2BYTE2)begin
next_state = BYTE2;
end
end
default next_state = 2'd0;
endcase
end
assign BYTE12BYTE1 = in[3] == 0;
assign BYTE12BYTE2 = in[3] == 1;
assign DONE2BYTE1 = in[3] == 0;
assign DONE2BYTE2 = in[3] == 1;
// Output logic
assign done = (state == DONE);
endmodule
知识点:
提示:
-
尽管 in[7:0] 是一个字节,但 FSM 只有一个输入:in[3]。
-
您需要 4 个状态。三个状态可能行不通,因为其中一个状态需要断言 done,而对于每个收到的消息,done 只会断言一个周期。
7 PS/2 packet parser anddatapath | PS/2 数据包解析器和数据路径
题目:
现在您有了一个可以识别 PS/2 字节流中的三字节消息的状态机,请添加一个数据路径,该数据路径还会在收到数据包时输出 24 位(3 字节)消息(out_bytes[23:16] 是第一个字节,out_bytes[15:8] 是第二个字节,等等)。
只要 done 信号被置位,out_bytes 就必须有效。您可以在其他时间输出任何内容(即,无关紧要)。
例如:
答案:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
// FSM from fsm_ps2
reg [1:0] state, next_state;
parameter BYTE1=2'd0, BYTE2=2'd1, BYTE3=2'd2, DONE=2'd3;
wire BYTE12BYTE1,BYTE12BYTE2,DONE2BYTE1,DONE2BYTE2;
// State transition logic (combinational)
always @(posedge clk) begin
if(reset)begin
state <= BYTE1;
end
else begin
state <= next_state;
end
end
always @(*) begin
case(state)
BYTE1 : begin
if (BYTE12BYTE1)begin
next_state = BYTE1;
end
else if (BYTE12BYTE2)begin
next_state = BYTE2;
end
end
BYTE2 : begin
next_state = BYTE3;
end
BYTE3 : begin
next_state = DONE;
end
DONE : begin
if (DONE2BYTE1)begin
next_state = BYTE1;
end
else if (DONE2BYTE2)begin
next_state = BYTE2;
end
end
default next_state = 2'd0;
endcase
end
assign BYTE12BYTE1 = in[3] == 0;
assign BYTE12BYTE2 = in[3] == 1;
assign DONE2BYTE1 = in[3] == 0;
assign DONE2BYTE2 = in[3] == 1;
// Output logic
assign done = (state == DONE);
// New: Datapath to store incoming bytes.
reg [23:0] in_temp;
always @(posedge clk) begin
in_temp <= {in_temp[15:0],in};
end
assign out_bytes = (state == DONE) ? in_temp : 0 ;
endmodule
知识点:
提示:
使用 PS/2 数据包解析器的 FSM 并添加数据路径来捕获传入的字节。
讲解:
在上题基础上,增加三个字节的寄存器,在 DONE 状态时输出数据即可。
- END -
公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转:
望森FPGA的HDLBits合集