400 likes | 528 Views
Introduction to FPGA Development. Justin Thiel Two Sigma Investments. Mapping Operations to HW. always @( posedge clk ) begin r_x <= x; if (x) r_y <= r_x ; end. Flip Flop. Flip Flop. r_y. x. r_x. clk. What is Inside an FPGA?. What is Inside an FPGA?. a + b = c.
E N D
Introduction to FPGA Development Justin ThielTwo Sigma Investments
Mapping Operations to HW always @(posedgeclk) begin r_x <= x; if (x) r_y <= r_x; end Flip Flop Flip Flop r_y x r_x clk
What is Inside an FPGA? a + b = c LUT Inputs (Address) LUT Outputs (Data)
module ttl74163 #( parameter WIDTH = 4 ) ( input clk, input rst_n, input [WIDTH-1:0] i_load_cnt, input i_load_n, input i_cnt_en, input i_cnt_en_w_carry_out, output [WIDTH-1:0] o_cnt, output o_carry_out ); // Some sweet logic here ... endmodule
Exercise 1 74163 Binary Counter Simulation
Verilog Numerical Types Format: [WIDTH]’[BASE][VALUE] 2’d0 -> 2 bit decimal 0 2’b0 -> 2 bit binary 0 4’he -> 4 bit hexadecimal 14 4’o7 -> 4 bit octal 7 • Arbitary bit widths are allowed • Hex (h), Binary (b), Decimal (d), and octal (o) bases are handled • Same numeric form is used for everything (no floats, doubles, etc..) • For “signed” integers logic tends to use 2s complement format
Verilog Operators Bitwise: OR: 3’b010 | 3’b100 -> 3’h110 AND: 3’b100 & 3’b111 -> 3’b100 XOR: 3’b101 ^ 3’b110 -> 3’b011 NOT: ~3’b101 -> 3’b010 Arithmetic: Addition : 3’b010 + 3’b100 -> 3’b110 Subtraction: 3’b100 – 3’b001 -> 3’b011 Comparators: Greater Than: (3’b100 > 3’b011) -> 1’b1 Equality : (3’b100 == 3’b010) -> 1’b0 Inequality : (3’b100 != 3’b000) -> 1’b1
Verilog Concepts wire w_rst; assignw_rst= ~rst_n; • wires are used to define “stateless” signals • They can only be assigned to by a (single) assign statement • The value of a wire changes whenever the inputs to it’s assign statement transition clk w_rst rst_n rst_n w_rst
Verilog Concepts regr_en_a; always@(posedgeclk) begin r_en_a<=i_en_a; end • regs are used to define “stateful” signals. • They should only be assigned to within a (single) always block • The value of a regchanges only when its always block evaluates Flip Flop r_en_a i_en_a clk i_en_a r_en_a clk
Verilog Concepts regr_en_a; regr_en_b; always@(posedgeclk) begin r_en_a <= i_en_a; r_en_b <= r_en_a; end • All statements in an always block evaluate in parallel. Flip Flop Flip Flop i_en_a r_en_a r_en_b clk i_en_a r_en_a r_en_b clk clk
Verilog Concepts regr_en_a; regr_en_b; always@(posedgeclk) begin r_en_a <= i_en_a; end always@(posedgeclk) begin r_en_b <= r_en_a; end • All always blocks execute in parallel. Flip Flop Flip Flop i_en_a r_en_a r_en_b clk i_en_a r_en_a r_en_b clk clk
Verilog Concepts regr_rst; always@(*) begin r_rst <= ~rst_n; End ..Same as... always@(rst_n) begin r_rst <= ~rst_n; end • always blocks are not required to be clocked • Making a block sensitive to ‘*’ causes it to evaluate whenever a right-hand side value changes clk r_rst rst_n rst_n r_rst
Dealing with Bits // 1 bit wire Wire w_rst; // 4 bit register reg [3:0] r_cnt; // 1024 bit wire wire [1023:0] x; // 4x 32b registers reg [31:0] r_data [3:0]; // 4x4x 32b registers reg [31:0] r_data2d [3:0][3:0]; • Brackets ‘[]’ are used to denote multi-bit fields
Dealing with Bits wire [3:0] x; wire y; wire [1:0] z; // Set y to Bit 0 of x assign y = x[0]; // Set z to Bits 1:0 of x assign z = x[1:0]; • Brackets ‘[…]’ are also used to bit slice vectors. • Use ‘:’ to specify a range. x[1] x[0] y z[0] z[1]
Dealing with Bits wire [3:0] x [1:0]; wire [3:0] y; wire [3:0] z; // Pulling Array Entries assign x[0] = y; assign x[1] = z; • Brackets ‘[…]’ are also used to index into arrays z y x[0] x[1]
Dealing with Bits wire [1:0] x; wire y; wire z; // Set x[1] to y, x[0] to z of y and z assign x = {y,z}; • Use curly braces ‘{…}’ to concatenate bit vectors z y x[1] x[0]
Module Declaration and Port Maps module ttl74163 #( parameter WIDTH = 4 ) ( // Clock and Reset Pins input clk, input rst_n, // Inputs input [WIDTH-1:0] i_load_cnt, input i_load_n, ... // Outputs output [WIDTH-1:0] o_cnt, output o_carry_out ); • Alldesignsstart with a module declaration
Module Declaration and Port Maps module ttl74163 #( parameter WIDTH = 4 ) ( // Clock and Reset Pins input clk, input rst_n, // Inputs input [WIDTH-1:0] i_load_cnt, input i_load_n, ... // Outputs output [WIDTH-1:0] o_cnt, output o_carry_out ); • parameters can be used to create logic which is configurable at compile (synthesis) time • They must be enclosed within a “#( … )” block
Module Declaration and Port Maps module ttl74163 #( parameter WIDTH = 4 ) ( // Clock and Reset Pins input clk, input rst_n, // Inputs input [WIDTH-1:0] i_load_cnt, input i_load_n, ... // Outputs output [WIDTH-1:0] o_cnt, output o_carry_out ); • Inputs denote signals which are driven outside the module • Outputs denote signals which are driven by the module • These signals form the portmap and are enclosed in a “(…)” block i_load_cnt ttl74163 o_cnt i_load_n o_carry_out
Module Instantiation parameter MY_WIDTH = 4; wire [MY_WIDTH-1:0] w_load_cnt; wire w_load_n; wire [MY_WIDTH-1:0] w_cnt; wire w_carry_out; ttl74163 #( .WIDTH (MY_WIDTH) ) my_ttl_counter ( .clk (clk), .rst_n (rst_n), .i_load_cnt (w_load_cnt), .i_load_n (w_load_n), ... .o_cnt (w_cnt), .o_carry_out (w_carry_out)); • Inputs and Outputs should be connected to wires/regs. • Each instance represents a unique copy of the logic defined in the module • agiven module is a unique copy of the logic w_load_cnt my_ttl_counter w_cnt w_load_n w_carry_out
Verilog Constructs reg [3:0] r_cnt; wire [3:0] w_cnt; always@(posedgeclk) begin // Clear if (rst) r_cnt<= '0; else r_cnt<= w_cnt; end • Simpleif..elseblocks synthesize as a 2-to-1-mux • This construct can only be used in an always block. Flip Flop 4’d0 1 r_cnt w_cnt 0 rst clk
Verilog Constructs regr_set; always@(posedgeclk) begin r_set <= (rst) ? 0 : i_set; end ... wire w_set; assign w_set = (rst) ? 0 : i_set; • Ternaryoperators (?) also imply a 2-to-1 mux • Can be used in always blocks or assign statements. Flip Flop 1’b0 1 w_set r_set i_set 0 rst clk
Verilog Constructs reg[1:0] r_cnt; wire w_a, w_b; always@(posedgeclk) begin case ({w_a, w_b}): 2’b01: r_cnt <= 2’d1; 2’b10: r_cnt <= 2’d1; 2’b00: r_cnt <= 2’d0; 2’b11: r_cnt <= 2’d2; default: r_cnt <= 2’d0; endcase end • case statements will (generally) imply an n-to-1 mux • This construct can only be used in an always block. • default case is a failsafe, provide for best results 2’b00 Flip Flop 2’b01 r_cnt 2’b10 2’b11 {w_a, w_b} clk
Verilog Constructs reg[1:0] r_cnt; wire w_en; always@(posedgeclk) begin if (w_en) r_cnt <= r_cnt + 1; else r_cnt <= r_cnt; end • Arithmeticoperations synthesize into physical representations thereof 2x Flip Flops 0 r_cnt 2’d1 2 bit Adder 1 clk w_en
Verilog Constructs // Full Adder Example module full_adder( input i_a, input i_b, input i_cin, output o_sum, output o_cout ); wire w_tmp; assign w_tmp = (i_a ^ i_b); assign o_sum = (w_tmp ^ i_cin); assign o_cout= (i_a & i_b) | (i_cin & w_tmp); endmodule; • You can also build arithmetic operators yourself…
Verilog Constructs reg[3:0] r_cnt; always@(posedgeclk) begin // Clear if (w_rst) r_cnt<= '0; // Load value else if (w_load) r_cnt<= i_cnt; // Count else if (w_cnt_en) r_cnt<= r_cnt + 1; else r_cnt<= r_cnt; end • if..else if...else blocks imply priority just as they do in a C/C++. • In this case, w_rst takes priority, followed by w_load and so on…
Verilog Constructs else if (w_cnt_en) r_cnt <= r_cnt + 1; else r_cnt <= r_cnt; end always@(posedgeclk) begin if (w_rst) r_cnt<= '0; else if (w_load) r_cnt <= i_cnt; ... 4’d1 4bit Full Adder 0 0 4x Flip Flops 0 1 r_cnt i_cnt 4’d0 1 1 w_cnt_en w_load clk w_rst
Syntactic Sugar wire [3:0] x; wire [3:0] y; wire [3:0] z; assign x = ‘0; assign y = ‘1; assign z = (x == ‘1) ? x : y; • ‘0 = “all bits set to zero” • ‘1 = “all bits set to one”
Summary • Use wires for purely combinatorial logic and regs for anything stateful • Areg does not always imply a flip flop • SimpleIf…Else and Ternary statements synthesize into 2-to-1 muxes • Chains of If…Else If…Else blocks can lead to long timing paths • Acase statement will yield an n-to-1 mux when coded properly
Exercise 2 Binary Counter Modification
Exercise 2 - Hint clk i_en o_cnt 0 14 15 … 1 2 14 13 … 1 0 1 … clk Wrong r_cnt_dn o_cnt 0 14 15 … 1 2 0 15 14 13 12 11 … clk Correct r_cnt_dn o_cnt 0 1 2 14 15 … 14 13 … 1 0 1 …
Exercise 3 FPGA build flow