| 后一修订版 | 前一修订版 |
| eee:fpga:led_blink [2026/08/15 09:34] – 创建 xiaobenmao | eee:fpga:led_blink [2026/08/15 13:17] (当前版本) – ↷ 链接因页面移动而自动修正 xiaobenmao |
|---|
| ===== Assignment ===== | ===== Assignment ===== |
| |
| Here we use ''<='' (non-blocking assignment) instead of ''='' (blocking assignment), and they have different Verilog simulation semantics, which affects how a hardware description behaves and can cause simulation results to differ from the intended synchronous hardware behavior. In simulator, blocking assignment behaves like the programming language, the first line complete first (and blocking the next line to execute), then is the second line. While the the non-blocking assignment get ready all new values first, and then update all together. | Here we use ''<='' (non-blocking assignment) instead of ''='' (blocking assignment), and they have different Verilog simulation semantics, which affects how a hardware description behaves and can cause simulation results to differ from the intended synchronous hardware behavior. In simulator, blocking assignment behaves like the programming language, the first line complete first (and blocking the next line to execute), then is the second line. While the the non-blocking assignment get ready all new values first, and then update all together. Refer to page [[assignment]] for more details. |
| | |
| Consider the initial condition ''a = 1'' and ''b = 2'', if blocking assignment is used, | |
| | |
| <code verilog [enable_line_numbers="true"]> | |
| a = b; | |
| b = a; | |
| </code> | |
| | |
| will get the result that ''a = 2'' and ''b = 2'', since the value of ''a'' has been updated before the phrase ''b = a;''. | |
| | |
| The non-blocking assignment | |
| | |
| <code verilog [enable_line_numbers="true"]> | |
| a <= b; | |
| b <= a; | |
| </code> | |
| | |
| can swap them nicely that ''a = 2'' and ''b = 1''. | |
| |
| For beginner, it is good to keep all sequential logic with non-blocking assignment ''<='', and combinational logic in blocking assignment ''=''. | For beginner, it is good to keep all sequential logic with non-blocking assignment ''<='', and combinational logic in blocking assignment ''=''. |
| ===== Counting ===== | ===== Counting ===== |
| |
| The [[eee:fpga:board:ypcb-00338]] board have a crystal of 50 MHz (and also another 2 in 200 MHz). In order to toggle LED every 1 second, or 2 Hz, we need to count from 0 to 49,999,999, and then toggle ''led'' and reset counter. | The [[eee:fpga:board:ypcb-00338-1p1]] board have a crystal of 50 MHz (and also another 2 in 200 MHz). In order to toggle LED every 1 second, or 2 Hz, we need to count from 0 to 49,999,999, and then toggle ''led'' and reset counter. |
| |
| <code verilog [enable_line_numbers="true"]> | <code verilog [enable_line_numbers="true"]> |
| Similarly, we need to attach ports to physical pins. | Similarly, we need to attach ports to physical pins. |
| |
| <code - top.xdc [enable_line_numbers="true"]> | <code xdc top.xdc [enable_line_numbers="true"]> |
| set_property PACKAGE_PIN AA28 [get_ports clk] | set_property PACKAGE_PIN AA28 [get_ports clk] |
| set_property IOSTANDARD LVCMOS18 [get_ports clk] | set_property IOSTANDARD LVCMOS18 [get_ports clk] |
| The ''counter0_i'' adds up ''counter0_i.I0[25:0]'', which is the current value of register ''counter_reg[25:0]'' (''counter_reg[25:0].Q''), and ''counter0_i.I1'', which is connected to high level directly. The value is temporarily kept at ''counter0_i.O[25:0]'', or ''counter_reg[25:0].D''. When the ''clk'' at posedge, ''counter_reg[25:0]'' will be updated from ''counter_reg[25:0].D''. This is how the sentence | The ''counter0_i'' adds up ''counter0_i.I0[25:0]'', which is the current value of register ''counter_reg[25:0]'' (''counter_reg[25:0].Q''), and ''counter0_i.I1'', which is connected to high level directly. The value is temporarily kept at ''counter0_i.O[25:0]'', or ''counter_reg[25:0].D''. When the ''clk'' at posedge, ''counter_reg[25:0]'' will be updated from ''counter_reg[25:0].D''. This is how the sentence |
| |
| <code verilog> | <code verilog [enable_line_numbers="true"]> |
| counter <= counter + 1; | counter <= counter + 1; |
| </code> | </code> |
| The ''counter0_i__0'' compares ''counter0_i__0.I0[25:0]'' (''counter_reg[25:0].Q'') and a fixed value at ''counter0_i__0.I1[25:0]'', ''0x2FAF07F'', or 49,999,999. The output ''counter0_i__0.O'' goes to two places, one is ''counter_reg[25:0].RST'', which will reset the value, and the other is ''led_state_reg.CE''. This corresponds to the block | The ''counter0_i__0'' compares ''counter0_i__0.I0[25:0]'' (''counter_reg[25:0].Q'') and a fixed value at ''counter0_i__0.I1[25:0]'', ''0x2FAF07F'', or 49,999,999. The output ''counter0_i__0.O'' goes to two places, one is ''counter_reg[25:0].RST'', which will reset the value, and the other is ''led_state_reg.CE''. This corresponds to the block |
| |
| <code verilog> | <code verilog [enable_line_numbers="true"]> |
| if (counter >= 26'd49_999_999) begin | if (counter >= 26'd49_999_999) begin |
| counter <= 0; | counter <= 0; |
| The ''led_state_reg'' is another register similar to ''couter_reg[25:0]''. It will only take action when ''led_state_reg.CE'' (clock enable) is high. When ''led_state_reg.CE'' is high and ''led_state_reg.C'' is at posedge, it will update its value from ''led_state_reg.D'', which is operated from ''led_state_reg.Q'' using an inverter ''led_state0_i''. This correcponds the phrase | The ''led_state_reg'' is another register similar to ''couter_reg[25:0]''. It will only take action when ''led_state_reg.CE'' (clock enable) is high. When ''led_state_reg.CE'' is high and ''led_state_reg.C'' is at posedge, it will update its value from ''led_state_reg.D'', which is operated from ''led_state_reg.Q'' using an inverter ''led_state0_i''. This correcponds the phrase |
| |
| <code> | <code verilog [enable_line_numbers="true"]> |
| led_state <= ~led_state; | led_state <= ~led_state; |
| </code> | </code> |