显示页面过去修订反向链接全部折叠/展开回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== LED Blink ====== Create an empty project like [[led_toggle]] did. ===== Clock ===== Sequential RTL usually describes behavior in terms of clock edges rather than absolute time. ''always @(posedge clk)'' reacts to each rising edge regardless of whether the clock is 50 MHz or 100 MHz. However, the physical circuit does care about the clock period, because the combinational logic between registers must settle before the next sampling edge. For example, <code verilog [enable_line_numbers="true"]> always @(posedge clk) begin counter1 <= counter1 + 1; counter2 <= counter2 + 1; end </code> This block is asking the FPGA to increase both ''counter1'' and ''counter2'' signals by 1 when at ''clk'' signal ''posedge'' (raising from ''0'' to ''1''). Take note that the change of both signals happen at the same time independently, as they are parallel in physical space. It will not like programming language to increase ''counter1'' first then increase ''counter2''. ===== 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. Refer to page [[assignment]] for more details. For beginner, it is good to keep all sequential logic with non-blocking assignment ''<='', and combinational logic in blocking assignment ''=''. ===== Counting ===== 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"]> if (counter >= 26'd49_999_999) begin counter <= 0; led <= ~led; end else begin counter <= counter + 1; end </code> We need the counter signal that is at least able to store 49,999,999. Since $$ 2^{25} = 33,554,432 < 50,000,000 \\ 2^{26} = 67,108,864 > 50,000,000 $$ 26-bit is enough. Thus the definition of counter should be <code verilog [enable_line_numbers="true"]> reg [25:0] counter; </code> where the MSB is bit 25 and LSB is bit 0. ===== Initialization ===== Before we combining everything together, we need to give initial values to our regs ''counter'' and ''led_state'', so that they are not starting from any random values that we are not expecting. <code verilog top.v [enable_line_numbers="true"]> initial begin counter = 0; led_state = 0; end </code> For this Xilinx 7-series FPGA using Vivado, synthesizable ''initial'' assignments can specify the configuration-time initial values of registers. The FPGA does not execute the ''initial'' block like software; Vivado maps the requested initial state into the device configuration. ===== Top Module ===== The top module will be <code verilog top.v [enable_line_numbers="true"]> module top ( input wire clk, output wire led ); reg [25:0] counter; reg led_state; initial begin counter = 0; led_state = 0; end always @(posedge clk) begin if (counter >= 26'd49_999_999) begin counter <= 0; led_state <= ~led_state; end else begin counter <= counter + 1; end end assign led = led_state; endmodule </code> ===== Constraint ===== Similarly, we need to attach ports to physical pins. <code xdc top.xdc [enable_line_numbers="true"]> set_property PACKAGE_PIN AA28 [get_ports clk] set_property IOSTANDARD LVCMOS18 [get_ports clk] set_property PACKAGE_PIN P30 [get_ports led] set_property IOSTANDARD LVCMOS18 [get_ports led] create_clock -period 20.000 [get_ports clk] </code> One additional line ''create_clock -period 20.000 [get_ports clk]'' is telling Vivado that the ''clk'' signal have a period of 20 ns, to asking analyzer that the logic must be completed within this period. ===== Result ===== It is expected that the red LED in sequence that lights up one second and blows down one second. ===== Register-Transfer Level (RTL) Schematic ===== Open left side menu - analysis - open elaborated design - schematic, you will see the electronic diagram from the Verilog code. {{.:pasted:20260815-084711.png}} 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 [enable_line_numbers="true"]> counter <= counter + 1; </code> works. 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 [enable_line_numbers="true"]> if (counter >= 26'd49_999_999) begin counter <= 0; led_state ... end </code> 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 verilog [enable_line_numbers="true"]> led_state <= ~led_state; </code> When ''led_state_reg.CE'' is low, ''led_state_reg.Q'' remains the same regardless of ''led_state_reg.C'', and nothing will be changed. ===== Synthesized Schematic ===== From left side menu - synthesis - open synthesized design - schematic, how the FPGA actually plan the resources will be shown. {{.:pasted:20260815-091250.png}} The input ''clk'' signal will go through input buffer ''IBUF'' and global clock buffer ''BUFG'' before it can be used. And the output signal ''led'' must be processed via output buffer ''OBUF''. The ''RTL_REG_SYNC'' ''counter_reg[25:0]'' and ''RTL_REG'' ''led_state_reg'' from RTL schematic is expanded to multiple ''FDRE'' (D-type Flip-Flop primitive), the ''RTL_ADD'' ''counter0_i'' is also replaced with multiple ''CARRY4'' dedicated fast carry-chain primitive used to implement arithmetic and comparison logic. ''RTL_GEQ'' ''counter0_i__0'' and ''RTL_INV'' ''led_state0_i'' are formed using multiple ''LUT'' (look-up table) unit, which stores the truth table of different blocks. ===== Mental Model ===== Verilog is not a sequence of instructions executed by the FPGA. Clocked registers store the current state. Combinational logic continuously computes values from the current signals. At a clock edge, registers sample their inputs and establish the next state. Vivado progressively transforms: RTL description → elaborated logic → FPGA primitives → placed and routed hardware → bitstream eee/fpga/led_blink.txt 最后更改: 2026/08/15 13:17由 xiaobenmao