ArticleDirectory
- 1 Arithmetic Circuit
- 2. Data Comparator
- 3 shift operation
Reader's assumptions
Mastered:
- Programmable Logic Basics
- Base on OpenGL
- Verilog us II Getting Started Guide designed with OpenGL
- ModelSim Getting Started Guide designed with OpenGL
Content 1 Arithmetic Circuit
In OpenGL, +,-, *,/, and % can all be integrated. The resources consumed vary depending on the device resources. For example, "+" and "-" are combined into adder, and each bit consumes about one le (Cyclone II). * is combined into a multiplier. If the device contains a multiplier, the underlying layer is mapped to a multiplier; otherwise, Le is used. We will discuss it later.
1.1 addition operations +
Code1.1 addition operations (Comprehensive)
Module Arithmetic (input [7: 0] IA, input [7: 0] IB, output [8: 0] oadd); assign oadd = Ia + IB; endmodule
Figure 1.1 RTL view and resource consumption of addition operations
1.1 shows that the addition operation is integrated into adder, and its resource consumption is about 1 le/BIT (corresponding to the LUT-4 structure of Cyclone II le ).
Code 1.2 adds testbench (not comprehensive, used for simulation only)
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _ B = 8' b0100 _ 1000; wire [] o_add; initial #100 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. IB (I _ B ),. oadd (o_add); endmodule
Figure 1.2 functional simulation of addition operations
1.2 Multiplication operation *
Code 1.3 multiplication code
Module Arithmetic (input [] IA, input [] IB, output [] omul); assign omul = Ia * Ib; endmodule
Figure 1.3 The multiplication operation calls lpm_mult directly
Figure 1.4 RTL view and resource consumption of multiplication
Looking at the comprehensive results, we found that the X of cylone II is directly mapped to the multiplier. Here is embedded multiplier 9-bit elements. In fact, the multiplier embedded in Cyclone II is 18 bits, and each multiplier can be split into two 9 bits.
Code 1.4 multiplication testbench
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _ B = 8' b0100 _ 1000; wire [] o_mul; initial #100 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. IB (I _ B ),. omul (o_mul); endmodule
Figure 1.5 Waveform Simulation of multiplication
1.3 division operation/
Code 1.5 Division
Module Arithmetic (input [7:0] IA, input [7:0] IB, output [7:0] odiv); assign odiv = IA/IB; endmodule
After integration, we found that the division operation was implemented by calling lpm_divide directly.
Figure 1.5 The division operation calls lpm_divide directly
Figure 1.6 RTL view and resource consumption of Division operations
As shown in Figure 1.6, although the Division operation can directly call macros, its resource consumption is also very huge, and each division consumes about 10 le.
Code 1.6 division testbench
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _ B = 8' b0100 _ 1000; wire [] o_div; initial #100 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. IB (I _ B ),. odiv (o_div); endmodule
Figure 1.7 functional Waveform Simulation of Division operations
1.4 remainder operation %
Code 1.7 remainder operation
Module Arithmetic (input [7:0] IA, input [7:0] IB, output [7:0] OMOD); assign OMOD = Ia % Ib; endmodule
Like Division operations, the remainder operation is directly implemented by calling lpm_divide.
Figure 1.8 using the remainder operation to directly call macro implementation
Figure 1.9 comprehensive RTL view and resource consumption of remainder operations
Code 1.8: testbench of the remainder operation
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _ B = 8' b0100 _ 1000; wire [] o_mod; initial #100 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. IB (I _ B ),. OMOD (o_mod); endmodule
Figure 1.10 function simulation waveform of the remainder operation
2. Data Comparator
Code 2.1 data comparator (Comprehensive)
Module Arithmetic (input [3: 0] IA, input [3: 0] IB, output oeq, // equals to output oneq, // not equal to output ogt, // greater than output ogt_eq, // greater than or equal to output OLT, // less than output olt_eq // less than or equal to); assign oeq = (IA = Ib), oneq = (Ia! = Ib), ogt = (IA> Ib), ogt_eq = (IA> = Ib), OLT = (IA <Ib), olt_eq = (IA <= Ib); endmodule
Observe 12th ~ Line 17: The description of the data comparator is very consistent with that of the C language.
Assign oeq = (IA = Ib), oneq = (Ia! = Ib), ogt = (IA> Ib), ogt_eq = (IA> = Ib), OLT = (IA <Ib), olt_eq = (IA <= Ib );
Figure 2.1 combined RTL view of the data Comparator
Code 2.2: testbench of the Data comparator (not comprehensive, used for simulation only)
'Timescale 1ns/1 nsmodule success; Reg [] I _a; Reg [] I _ B; wire o_eq, o_neq, o_gt, o_gt_eq, o_lt, o_lt_eq; initial begin I _a = 5; I _ B = 5; #20 I _a = 6; #20 I _a = 4; #20 $ stop; endarithmetic arithmetic_inst (. ia (I _a ),. IB (I _ B ),. oeq (o_eq ),. oneq (o_neq ),. ogt (o_gt ),. ogt_eq (o_gt_eq ),. olt (o_lt ),. olt_eq (o_lt_eq); endmodule
Figure 2.2 functional simulation waveform of the Data Comparator
3 shift operation
Veirlog HDL 2001 supports logical shift and arithmetic shift.
3.1 logical shift
Code 3.1 logical shift (Comprehensive)
Module Arithmetic (input [] IA, input [] ibit, // shift the number of digits 0 ~ 7 output [] osll, // logically shift left output [] osrl // logically shift right); assign osll = (IA <ibit ), osrl = (IA> ibit); endmodule
8th ~ The symbols of logical shift are the same as those of the C language: >>( logical right shift, shift right logical); <(logical left shift, shift left logical ). If multiple statements exist after the assign keyword, they can be separated by commas (,). You can also use two assign statements to describe them separately.
Assign osll = (IA <ibit), osrl = (IA> ibit );
Figure 3.1 RTL view of logical shift
Code 3.2 logical shift testbench
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _bit = 0; wire [] o_sll, o_srl; initial while (I _bit <7) #20 I _bit = I _bit + 1 'b1; initial #160 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. ibit (I _bit ),. osll (o_sll ),. osrl (o_srl); endmodule
3rd ~ Line 4: the initial value is assigned when the reg-type signal is declared.
Reg [] I _a = 8 'b1011 _ 0111; Reg [] I _bit = 0;
6th ~ Seven lines of signals of the same type and equal-bit width can be separated by commas.
Wire [7:0] o_sll, o_srl;
Row 3 uses the while statement to generate incentives, which are used in the same way as the C language.
Initial while (I _bit <7) #20 I _bit = I _bit + 1' B1;
Right-click the expected signal and selectRadix> unsignedTo view I _bit in unsigned decimal format. 3.2.
Figure 3.2 I _bit in unsigned decimal format
Figure 3.3 functional simulation waveform of logical shift
3.2 arithmetic shift
For the differences between arithmetic shift and logical shift, see 3.
Code 3.3 logical shift and arithmetic shift of signed numbers (Comprehensive)
Module Arithmetic (input Signed [] IA, input [] ibit, // shift the number of digits 0 ~ 7 output Signed [] osll, // logically shift left output Signed [] osrl, // logically shift right output Signed [] oasl, // arithmetic shift left output Signed [] oasr // arithmetic shift right); assign osll = (IA <ibit), osrl = (IA> ibit ), oasl = (IA <ibit), oasr = (IA> ibit); endmodule
2nd ~ In the seven rows, the number of shifts is declared as the number of unsigned digits, and the migrated data and its results are declared as the number of signed digits.
Input Signed [] IA, input [] ibit, // The number of shifted digits 0 ~ 7 output Signed [] osll, // logically shift left output Signed [] osrl, // logically shift right output Signed [] oasl, // arithmetic shift left output Signed [] oasr // arithmetic shift right
10th ~ 13 rows. Different from logical shift, the arithmetic shift operator is: <(arithmetic left shift, arithmetic shift left); >>> (arithmetic right shift, arithmetic shift right ).
Assign osll = (IA <ibit), osrl = (IA> ibit), oasl = (IA <ibit), oasr = (IA> ibit );
Figure 3.4 RTL view of logical shift and arithmetic shift of signed numbers
Code 3.4 the logical shift of the signed number and the testbench of the arithmetic shift (not comprehensive, used for simulation only)
'Timescale 1ns/1 nsmodule arithmetic_tb; Reg Signed [] I _a = 8 'sb1011 _ 0111; Reg Signed [] I _bit = 0; wire Signed [] o_sll, o_srl, o_asl, o_asr; initial while (I _bit <7) #20 I _bit = I _bit + 1 'b1; initial #160 $ stop; arithmetic arithmetic_inst (. ia (I _a ),. ibit (I _bit ),. osll (o_sll ),. osrl (o_srl ),. oasl (o_asl ),. oasr (o_asr); endmodule
Right-click all signals and selectRadix> binaryIn binary format. 3.5.
Figure 3.5 view all signals in binary format
Figure 3.6 simulation waveform of the logic shift and arithmetic shift functions of the signed number
Conclusion: The result of the arithmetic shift left is the same as that of the logical shift left. The arithmetic shift right is filled with the symbol bit while the logical shift right is filled with 0.
Secondary reading
1. Altera. Recommended HDL coding styles
Reference
1. Signed arithmetic in OpenGL 2001-Opportunities and hazards
2. http://iroi.seu.edu.cn/books/asics/Book2/CH11/CH11.03.htm
3. What is the difference between bsdc and logical shift?
See also
[Study FPGA/FPGA with Amy]. [logical experiment document serialization plan]