**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 select**Radix> unsigned**To 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 select**Radix> binary**In 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]