161
Thi ết kế và t ng hp hthng s 2012 (C) [email protected] (www.edabk.org) ddas.edabk.org

Thiết kế và tổng hợp hệ thống số-Bài Giảng

Embed Size (px)

Citation preview

Thiết kế và tổng hợp hệ thống số 2012 (C) [email protected] (www.edabk.org) ddas.edabk.org

1 Chương 1: Giới thiệu thiết kế mạch số

1.1 1.1 Các khái niệm cơ bản trong thiết kế mạch số

1.1.1 1.1.1 Định nghĩa: mạch điện tử là một hệ thống gồm các linh kiện điện tử biến đổi

tín hiệu (dòng điện, điện áp) đầu vào thành tín hiệu đầu ra

1.1.1.1 Để mô tả mạch điện tử: cần mô tả tín hiệu đầu vào, tín hiệu đầu ra, và hàm truyền

đạt của mạch

1.1.2 1.1.2 Phân loại

1.1.2.1 Mạch tương tự

1.1.2.2 Mạch số

Tín hiệu vào/ra chỉ có 2 mức thấp và mức cao

Mức 0,1

Mạch số tổ hợp

Hàm truyền đạt chỉ phụ thuộc vào đầu vào

Mạch số tuần tự (Mạch dãy)

Hàm truyền đạt phụ thuộc vào đầu vào và trạng thái hiện tại của mạch

Mạch đồng bộ

Trạng thái của mạch được lưu vào Flip Flop theo một tín hiệu nhịp (tín hiệu đồng hồ)

Mạch không đồng bộ

Trạng thái và hoạt động của mạch không theo đồng hồ

1.1.3 1.1.3. Đại số Bool và logic tổ hợp

1.1.3.1 Biến Bool

Biến đơn

a,b,x,y nhận các giá trị 0,1

Biến vector

a[3:0] nhận các giá trị {0,1}^4

1.1.3.2 Hàm Bool

Nhiều đầu vào, một đầu ra: MISO

Nhiều đầu vào, nhiều đầu ra: MIMO

Biểu diễn hàm Bool

Biểu thức Bool gồm

Các biến Bool

Các phép toán Bool

AND, OR, NOT, XOR

Bảng chân lý

Liệt kê tất cả các tổ hợp giá trị của các biến đầu vào

Liệt kê các giá trị hàm tương ứng

Là cách biểu diễn duy nhất

Kích thước rất lớn ~ hàm mũ của số biến

Bảng chân lý rút gọn

Kích thước nhỏ hơn

Không là duy nhất

Chỉ có thể dùng cho các mạch đơn giản, ít đầu vào

Tối ưu hàm Bool

Dùng cách tối giản bìa Karnaugh

http://en.wikipedia.org/wiki/Karnaugh_map

See document(s): Karnaugh_map

Dùng phương pháp Quine-McCluskey

http://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm

See document(s): Quine%E2%80%93McCluskey_algorithm

Triển khai hàm Bool bằng mạch logic tổ hợp

Gồm các cổng logic căn bản kết nối với nhau để tạo thành hàm truyền đạt

Kích thước ~ tuyến tính với số phép toán dùng trong hàm truyền đạt

1.1.3.3 Ví dụ:

Bộ giải mã 7 thanh

Bộ cộng

1.1.4 1.1.4. Máy trạng thái hữu hạn FSM

1.1.4.1 Hàm truyền đạt

Hàm trạng thái kế tiếp Delta

s' = delta(x,s)

s' trạng thái tiếp theo của mạch

s trạng thái hiện tại của mạch

x là đầu vào của mạch

Hàm đầu ra Lambda

Mealy: y = lambda(x,s)

More: y = lambda(s)

1.1.4.2 Biểu diễn FSM

Đồ thị chuyển trạng thái

Node: các trạng thái

Được dán nhãn là mã trạng thái tương ứng

Cạnh: chuyển trạng thái được dán nhãn là giá trị đầu vào tương ứng

Kích thước ~ số trạng thái ~ hàm mũ của số biến trạng thái

Bảng chuyển trạng thái và bảng đầu ra

1.1.4.3 Tối ưu FSM

Giảm số lượng trạng thái

Tìm các trạng thái tương đương

Mã hóa trạng thái

Mã one-hot, zero-hot, binary, gray

1.1.4.4 Triển khai FSM-Mạch dãy

Mã hóa các trạng thái, các ký hiệu vào và các ký hiệu ra bằng các biến Bool trạng thái, tín

hiệu vào và tín hiệu ra, tương ứng

Xác định hàm Bool cho trạng thái kế tiếp và cho đầu ra

Mạch tổ hợp trạng thái kế tiếp

Các Flip Flop

Mạch tổ hợp ra

1.1.4.5 Ví dụ

Bộ đếm

Bộ điều khiển đèn giao thông

Bộ điều khiển thang máy

Bộ điều khiển giao thức RS232, Bluetooth

1.1.5 1.1.5. Các phần tử phần cứng cơ bản

1.1.5.1 Transitor FET

1.1.5.2 Cổng logic cơ bản

1.1.5.3 Gate Netlist: mạng cổng

1.1.5.4 Standard Cell

Cell: Phần tử logic cơ bản, các khối chức năng cơ bản RAM, ROM...

Cấu trúc mô tả quy trình sản xuất

Chức năng logic

Mô hình tính thời gian

IC được chia làm các hàng và cột

Mỗi phần tử đặt một phần tử logic cơ bản: Cổng logic, RAM, ...

Các cell được kết nối thông qua dây kim loại

1.1.5.5 FPGA

Phần cứng có thể tái cấu hình: reconfigurable

Khối cơ bản LUT, LE: gồm bộ chọn MUX và SRAM

Bộ nhớ lưu bảng chân lý của hảm

Triển khai hàm logic

Giá trị bộ nhớ dùng điều khiển bộ MUX

Các khối được nối bằng đường dây có thể lập trình

1.2 1.2. Giới thiệu về HDL

1.2.1 1.2.1. Ngôn ngữ mô tả phần cứng (Hardware Description Language)

1.2.1.1 Mục đích

Mô hình và mô phỏng (có thời gian) thiết kế số

Có thể tổng hợp thành mạch bằng các công cụ tổng hợp

Synopsys Design Compiler

Altera Quatus

Xilinx ISE

Cadence

1.2.1.2 Phân loại

Verilog

Mềm dẻo

Sử dụng nhiều trong công nghiệp

VHDL

Sử dụng trong quốc phòng và thiết kế ô tô

Hướng kiểu mạnh

1.2.1.3 Ưu điểm của HDL

Cho phép thiết kế mạch rất lớn

Trừu tượng hơn sơ đồ mạch

Mô tả ở mức RTL-dịch chuyển thanh ghi

Sử dụng bit vector thay vì các bit đơn

Quá trình tổng hợp tự động sử dụng phần mềm EDA

Thiết kế có thể chuyển đổi

Thiết kế Verilog mô tả hành vi hoặc dòng dữ liệu có thể tổng hợp thành mạch dùng công nghệ

chế tạo mới với ít công sức (VD. Từ 0.13um sang 45nm)

Verilog ở dạng text, dễ dàng chuyển đổi giữa các chương trình khác nhau không như định

dạng nhị phân dùng riêng cho các chương trình vẽ mạch

Cho phép thử nghiệm, lựa chọn nhiều giải pháp thiết kế hơn

Các tùy chọn tổng hợp cho phép tối ưu và cân bằng các tham số về năng lượng, thời gian, kích

thước

Cho phép kiểm nghiệm thiết kế tốt hơn

Dùng Verilog để mô hình hóa môi trường hoạt động của mạch (testbench)

Phần mềm tổng hợp hoạt động tốt đảm bảo tính đúng đắn của hàm Bool được triển khai

1.2.1.4 Chú ý

Trông giống ngôn ngữ lập trình

Không phải ngôn ngữ lập trình

Luôn phải nhớ rằng đang mô tả phần cứng

Mã được dùng để tổng hợp ra phần cứng

Mã có thể được mô phỏng trên máy tính, chỉ là mục đích thứ 2

1.2.2 1.2.2. Ví dụ và các khái niệm ngôn ngữ cơ bản

1.2.2.1 module decoder_2_to_4 (A, D) ; input [1:0] A ; output [3:0] D ; assign D = (A ==

2'b00) ? 4'b0001 : (A == 2'b01) ? 4'b0010 : (A == 2'b10) ? 4'b0100 :

(A == 2'b11) ? 4'b1000 ; assign D[0] = (~A[1])*(~A[2]); endmodule

1.2.2.2 Một mạch điện là 1 module, được mô tả gồm các thành phần

Khai báo module

Tên

decoder_2_to_4

Đầu vào, đầu ra

Ports

A, D

Khai báo tín hiệu kết nối với đầu vào đầu ra

Kiểu port

Input

Output

Inout

Kích thước port

vô hương (đơn)

vector

[MSB:LSB]

Khai báo tín hiệu bên trong

Mô tả hoạt động của module

assign D = (A == 2'b00) ? 4'b0001 : (A == 2'b01) ? 4'b0010 : (A ==

2'b10) ? 4'b0100 : (A == 2'b11) ? 4'b1000 ;

1.2.3 1.2.3. Giới thiệu về phần mềm Quartus

1.2.3.1 http://www.youtube.com/watch?v=PDOTLuuKgqE

See document(s): watch

1.2.3.2 http://www.youtube.com/watch?v=PDOTLuuKgqE

See document(s): watch

1.2.4 1.2.4. Khái niệm mô phỏng và tổng hợp

1.2.4.1 Mô phỏng

Đưa tác động đầu vào (input stimuli) và quan sát so sánh đầu ra với đầu ra chuẩn (output

reference)

Hình vẽ

Kiểm tra mạch chiếm 90% công sức, giá thành làm ra mạch

1.2.4.2 Tổng hợp

Từ mô tả hoạt động mạch tạo ra phần cứng thực hiện hoạt động đó

Hình vẽ

Chú ý

Khác với chạy chương trình phần mềm tất cả các câu lệnh đều được tổng hợp thành phần

cứng

Học đề biết các câu lệnh Verilog HDL được chuyển thành phần cứng thế nào

Hình vẽ

1.3 1.3. Lưu đồ thiết kế hệ thống số dùng ngôn ngữ mô tả phần cứng

1.3.1 Hình vẽ

1.3.1.1

1.3.2 Chia làm 2 công đoạn chính

1.3.2.1 Front-end

Thiết kế ở mức hoạt động, mức logic

B1. Xác định các tham số kỹ thuật của mạch

Hiệu năng

Tần số hoạt động

Thông lượng dữ liệu (Data throughput)

Chức năng logic của mạch

Ví dụ: Thực hiện phép cộng, thực hiện phép biến đổi FFT

B2. Phân tích chức năng và chia thành các khối chức năng nhỏ (thiết kế sơ đồ khối)

B3. Mô tả hoạt động các khối chức năng bằng ngôn ngữ HDL

Kiểm tra mô phỏng từng khối chức năng

Kiểm chứng toán học các khối chức năng

B4. Ghép nối các khối chức năng thành toàn bộ hệ thổng

Kiểm tra mô phỏng toàn bộ hệ thống

B5. Tổng hợp mạch từ mức HDL thành mức cổng

Kiểm tra các yêu cầu thời gian của mạch

Kiểm chứng sự tương đương của mạch ở mức cổng và mức HDL

1.3.2.2 Back-end

Thiết kế ở mức vật lý

1.4 1.4. Ứng dụng và ví dụ về thiết kế số

1.4.1 Thiết kế bộ xử lý MIPS pipelined

1.4.1.1 Chức năng

Thực hiện các chương trình assembly theo kiến trúc tập lệnh MIPS

add, sub, addi

beq, bne

j

lw, sw

Pipeline 5 trạng thái

Chương trình được lưu trong bộ nhớ chương trình (bộ nhớ lệnh)

Dữ liệu lưu trong bộ nhớ dữ liệu

1.4.2 Thiết kế bộ truyền nhận số QAM16

1.4.2.1 Chức năng

Điều chế

Đầu vào: Dòng số 1 bit

Đầu ra: Dòng tín hiệu I/Q điều chế theo phương pháp QAM

Giải điều chế

Đầu vào: Dòng tín hiệu I/Q điều chế theo phương pháp QAM

Đầu ra: Dòng số 1 bit

Tùy chọn

Dòng tín hiệu I/Q cần được nhân với tín hiệu sóng mang

Tín hiệu sóng mang có thể được biến đổi thành tương tự bằng bộ DAC

Tín hiệu thu được tương tự được biến đổi thành số dùng ADC

Tin hiệu số thu được cần được đồng bộ và nhân với sóng mang sau đó giải điều chế

2 Chương 2. Các khái niệm cơ bản trong thiết kế số (ôn lại). Tham khảo:

Digital Design and Computer Architecture

2.1 2.1 Mạch logic tổ hợp

2.1.1 2.1.1 Đại số Bool

2.1.1.1 Biểu thức và hàm Bool

Biểu thức tổng các tích

sum of product

DNF

sum of minterm

canonical form

Biểu thức tích các tổng

product of sum

CNF

product of maxterm

canonical form

Tham khảo

Mục 2.2

2.1.1.2 Phép toán và phép biến đổi Bool

And, or, not, xor

Tiên đề trong đại số Bool

Các quy tắc/định lý trong đại số bool

Quy tắc AND/OR với 1/0

Luật giao hoán, kết hợp, phân phối

Biến đổi Demorgan

Định lý với 1 biến

Định lý nhiều biến

Sử dụng phép biến đổi Bool để tối giản biểu thức Bool

2.1.2 2.1.2 Triển khai hàm Bool

2.1.2.1 Các cổng logic cơ bản

Tham khảo

Mục 1.5 sách đã nêu

Not

Buffer

And

Or

XOR, NAND, NOR, XNOR

2.1.2.2 Từ biểu thức Bool đến mạch logic

Tham khảo

Mục 2.4

Schematic, Gate-Net list

Gồm các cổng logic và các dây dẫn nối các cổng logic

Cổng logic: các node trong đồ thị

Dây dẫn: các cạnh có hướng trong đồ thị

Input: các node không có node phía trước

Output: các node không có node phía sau

Fanout: Các node nối vào cạnh đi ra khỏi một node

Fanin: Các node nối vào các cạnh đi vào node

Ví dụ

Mạch logic nhiểu mức

Tham khảo

Mục 2.5

2.1.3 2.1.3 Tối ưu hàm Bool bằng bìa Karnaugh

2.1.3.1 Tham khảo

Mục 2.6

Mục 2.7

2.1.3.2 Ví dụ

2.1.4 2.1.4 Một số hàm Bool và mạch đơn giản

2.1.4.1 Hàm lựa chọn và bộ MUX

Triển khai bộ MUX 4-1

Hình vẽ bộ MUX 2-1

Sử dụng bộ MUX để thực hiện các hàm logic

2.1.4.2 Hàm giải mã và bộ giải mã

Bộ Decoder 2:4

2.1.4.3 Tham khảo

Mục 2.8

2.1.5 2.1.5 Hoạt động của mạch logic

2.1.5.1 Biểu đồ thời gian

Sườn lên: tín hiệu thay đổi từ mức logic thấp lên mức logic cao

Sườn xuống: tín hiệu thay đổi từ mức logic cao xuống mức logic thấp

Điểm 50%: thời điểm tín hiệu thay đổi giá trị được 50%

Hình vẽ

2.1.5.2 Thời gian

Thời gian đáp ứng của 1 cổng logic: Khoảng thời gian từ lúc đầu vào thay đổi đến khi đầu ra

thay đổi tương ứng

Đo từ điểm 50% của tín hiệu vào tới điểm 50% của tín hiệu ra

Độ trễ lan truyền (propagation delay) tpd

Thời gian từ lúc 1 đầu vào thay đổi đến khi đầu ra/các đầu ra đạt tới giá trị cuối cùng

trod = count t pdf ☹ of logic i train koreroing door what

Độ trễ ảnh hưởng (contamination delay) tcd

Thời gian từ khi 1 đầu vào thay đổi đến khi đầu ra bắt đầu thay đổi

tainted ong logic i train origin gain. what

Hình vẽ

Thời gian chuyển đổi (transition time)

Thời gian tín hiệu chuyển từ trạng thái 1->0 (falling time), và 0->1 (rising time): Đo bằng

khoảng cách giữa 2 điểm 10%-90% của tín hiệu

2.1.5.3 Đường tới hạn (đường dài nhất) - critical path và đường ngắn nhất

Đường dài nhất và chậm nhất trong mạch tổ hợp

Trễ lan truyền tpd là tổng trễ lan truyền của các cổng logic trên đường dài nhất

Trễ ảnh hưởng tcd là tổng các trễ ảnh hưởng của các cổng logic trên đường ngắn nhất

Ví dụ

Hình vẽ

2.1.5.4 Glitches/Hazards

1 sự thay đổi của đầu vào dẫn tới nhiều sự thay đổi ở đầu ra mà không phù hợp/tương ứng

với hàm logic

Hình vẽ

Loại trừ ành hưởng của hazards

Đợi đến khi đầu ra ổn định

Thêm cổng logic kết nối các prime implicants cách nhau

2.1.5.5 Tham khảo

Mục 2.9

2.2 2.2 Mạch dãy

2.2.1 2.2.1 Các phần tử nhớ cơ bản

2.2.1.1 Cấu trúc

Phần tử chốt SR

Phần tử chốt D

Thay đổi trạng thái khi CLK = 1 (level sensitive latch)

Phần từ D-Flip Flop

Thay đổi trạng thái khi có sườn lên của CLK

2.2.1.2 Mô tả hoạt động

Lưu trữ trạng thái

Chuyển đổi trạng thái

2.2.1.3 Mạch hoạt động theo đồng hồ

Tham khảo 3.3

Các phần từ nhớ trong mạch thay đổi trạng thái tại các sườn lên (xuống) của tín hiệu đồng

hồ

Hình vẽ

2.2.1.4 Tham khảo

Mục 3.2

2.2.1.5 Thực hành

Lab 3

ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Laboratory_Exercises/Digital_Logic/DE2/

verilog/lab3_Verilog.pdf

See document(s): lab3_Verilog.pdf

2.2.2 2.2.2 Máy trạng thái hữu hạn - FSM

2.2.2.1 Hàm Bool biểu diễn FSM

Hàm chuyển trạng thái

Hàm trạng thái kế tiếp Delta

s' = delta(x,s)

s' trạng thái tiếp theo của mạch

s trạng thái hiện tại của mạch

x là đầu vào của mạch

Hàm đầu ra

Hàm đầu ra Lambda

Mealy: y = lambda(x,s)

Moore: y = lambda(s)

2.2.2.2 Biểu diễn FSM bằng đồ thị chuyển trạng thái STG

Node: các trạng thái

Được dán nhãn là mã trạng thái tương ứng

Cạnh: chuyển trạng thái được dán nhãn là giá trị đầu vào tương ứng

Kích thước ~ số trạng thái ~ hàm mũ của số biến trạng thái

2.2.2.3 Mã hóa trạng thái bằng biến Bool

2.2.2.4 Biểu diễn hàm chuyển trạng thái bằng bảng chuyển trạng thái

2.2.2.5 Tham khảo

Mục 3.4

2.2.2.6 Thực hành

Lab 4. Phần 1

ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Laboratory_Exercises/Digital_Logic/DE2/

verilog/lab4_Verilog.pdf

See document(s): lab4_Verilog.pdf

2.2.2.7 Máy Moore/Mealy

2.2.3 2.2.3 Thời gian trong mạch dãy

2.2.3.1 Thời gian trong Flip-Flop

Setup time và hold time

Khoảng thời gian đầu vào D cần ổn định

Trễ lan truyền từ đồng hồ đến Q: Tpdq

Trễ ảnh hưởng từ đồng hồ đến Q: Tcdq

Hình vẽ

2.2.3.2 Thời gian hệ thống

Chu kỳ đồng hồ

Khoảng thời gian giữa 2 sườn lên (xuống) của tín hiệu đồng hồ Tc

2.2.3.3 Điều kiện thời gian setup

Đường trễ giữa 2 thanh ghi

Điều kiện về thời gian setup

Hình vẽ

Trong thực tế

Chu kỳ đồng hồ quyết định bởi khách hàng, thị trường, và giám đốc kỹ thuật để đảm bảo tính

cạnh tranh của sản phẩm

tsetup quyết định bởi nhà sản xuất

cần thiết kế phần mạch logic tổ hợp để thỏa mãn điều kiện thời gian setup

2.2.3.4 Điều kiện thời gian hold

Đầu vào D của FF không được thay đổi đến thold sau sườn lên (xuống) của clock

Hình vẽ

3 Chương 3. Cú pháp cơ bản của ngôn ngữ Verilog Tham khảo ví dụ:

http://www.asic-world.com

3.1 3.1. Chú thích

3.1.1 Giúp đọc code dễ dàng hơn cho người khác và về sau

3.1.2 Giúp gỡ lỗi dễ hơn

3.1.3 Không cần chú thích chức năng của đoạn code

3.1.3.1 Bản thân code chính là làm việc đó như thế nào nên không cần chú thích nữa

3.1.3.2 Ví dụ

always @(posedge clk) begin Sig_FF1 <= Sig // Capture value of Sig Line in FF Sig_FF2 <=

Sig_FF1; // Flop Sig_FF1 to form Sig_FF2 Sig_FF3 <= Sig_FF2; // Flow Sig_FF2 to form Sig_FF3 end

// start_bit is ~Sig_FF2 & Sig_FF3 assign start_bit = (~Sig_FF2 && Sig_FF3) ? 1’b1 : 1’b0;

signet-atop-Frito-Pa.-start. bit

3.1.4 Chú thích tại sao làm một việc

3.1.4.1 Ví dụ

always @(posedge clk) /******************************************** * Sig is ansynchronous

and has to be double flopped * * for meta-stability reasons prior to use

*********************************************/ begin Sig_FF1 <= Sig; Sig_FF2 <= Sig_FF1; //

double flopped meta-stability free Sig_FF3 <= Sig_FF2; // flop again for use in edge detection end

/********************************************** * Start bit in protocol initiated by falling edge of Sig

line * **********************************************/ assign start_bit = (~Sig_FF2 && Sig_FF3) ?

1’b1 : 1’b0;

3.1.5 Chú thích tương tự ngôn ngữ C

3.1.5.1 Nằm giữa /* */

3.1.5.2 Bắt đầu từ // đến cuối dòng

3.2 3.2. Khai báo module

3.2.1 Trong Verilog, để 1 mạch là 1 module

3.2.2 Hình vẽ

3.2.2.1

3.2.2.2

3.2.3 3.2.1. Khai báo module

3.2.3.1 Cú pháp

module module_name (list_of_port) port_declare; internal_signal_declare;

module_behavior_description endmodule

3.2.3.2 Tên module

Không được trùng với từ khóa

Nên chọn tên gợi nhớ chức năng module

3.2.3.3 Các cổng vào ra

3.2.3.4 Các tín hiệu bên trong module

3.2.3.5 Mô tả chức năng (hoạt động) của mạch

3.2.4 3.2.2.Khai báo cổng vào ra của module

3.2.4.1 Mỗi cổng vào ra tương ứng với 1 tín hiệu trong mạch

3.2.4.2 Khai báo kiểu của cổng port_type:

input

output

inout

bidirectional

3.2.4.3 Kích thước của cổng

vô hướng: một bit: input cin;

Vector: gồm nhiều bit - chỉ ra kích thước cụ thể trong 1 khoảng chỉ số [MSB:LSB]

Từ bit giá trị lớn nhất đến bit giá trị nhỏ nhất: từ trái sang phải

Chú ý: không cần bắt đầu từ chỉ số không

output [7:0] out; input [0:4] in;

3.2.4.4 Tóm lại, để khai báo 1 cổng: port_type [range] port_name;

3.2.4.5 Bài tập ví dụ: Khai báo module decoder 2:4 có tín hiệu enable

3.3 3.3. Khai báo các tín hiệu/biến/hằng bên trong mạch

3.3.1 3.3.1 Các giá trị dữ liệu trong Verilog

3.3.1.1 Kiểu logic

Có 4 giá trị

0: logic 0, điều kiện sai

1: logic 1, điều kiện đúng

x: không xác định: do chưa được khởi tạo hoặc xung đột

Hình vẽ

z: trở kháng cao: do không được nối với cổng logic, hoặc nối với cổng 3 trạng thái

Hình vẽ

Phép toán trên logic 4 giá trị

or

Hình vẽ

and

not

3 trạng thái

3.3.1.2 Kiểu số nguyên

Cú pháp chung

<size>'<base><number>

base nhận các giá trị> b, d, h, o

number có thể là

các chữ số (giá trị phụ thuộc cơ số)

x

z

size: chỉ ra kích thước (số bit) của số. Nếu không được chỉ rõ thì sẽ là giá trị mặc định của

phần mềm mô phỏng

Ví dụ

4'b1101

10'h2e7

12'h13x

số âm: -16'h3A

3.3.2 3.3.2 Khai báo biến/dây dẫn trong Verilog

3.3.2.1 Chú ý: Các biến trong Verilog thường được dùng để đại diện cho 1 phần tử vật lý

trong mạch. Ví dụ: dây dẫn, cổng logic, Flip-Flop

3.3.2.2 Cú pháp chung

type range identifier array_range

Tên biến: Identifier

Chọn tên có tính miêu tả, gợi nhớ

Chú ý: Dùng quy tắc nhất định để chỉ ra một tín hiệu là active-low

Ví dụ: rst_n

type

wire

biểu diễn dây dẫn trong mạch

Không lưu trữ giá trị

Cần được nối với cổng

Nhận giá trị của cổng điều khiển nó

Kết nối đầu ra và đầu vào khi thực thể hóa các module

Có thể khai báo tín hiệu input, output của module là wire

Không thể nằm bên trái phép gán = và <= trong khối always@

Là kiểu duy nhất có thể nằm bên trái phép gán dùng assign

Chỉ có thể dùng để mô tả logic tổ hợp

reg

biểu diễn cổng logic/flip flop trong mạch

lưu trữ giá trị cho đến khi được gán giá trị mới

chú ý không nhất thiết là flip flop

Có thể kết nối với 1 cổng vào của 1 module con

Không thể kết nối với 1 cổng ra của 1 module con

Có thể khai báo tín hiệu output là reg

Không thể khai báo tín hiệu input là reg

Là kiểu duy nhất nằm bên trái phép gán trong khối always và khối initial

Không thể nằm bên trái phép gán assign

Để mô tả thanh ghi nếu nằm bên trái phép gán trong khối always@(posedge clk)

Dùng để mô tả logic tổ hợp và logic tuần tự

wor, trior

wand, triand

tri

trireg

range

định nghĩa kích thước của biến

vector

tập hợp các bit

[msb:lsb]

array_range

dùng để định nghĩa một mảng (miêu tả bộ nhớ, tệp thanh ghi)

[index_1:index_2]

Ví dụ

wire [15:0] opA, opB, res;

reg [2:0] state, nxt_state;

reg [31:0] reg_files[0:15]

reg [31:0] mem[0:255]

3.3.3 3.3.3. Khai báo hằng số trong Verilog

3.3.3.1 Tăng tính biểu diễn, dễ hiểu

3.3.3.2 Tăng tính mềm dẻo, dễ thay đổi

3.3.3.3 define

định nghĩa hằng số toàn cục

ví dụ

`define idle = 2’b00; // idle state of state machine `define conv = 2’b01; // in this state while

A2D converting `define avg = 2’b10; // in this state while averaging samples

3.3.3.4 localparam

định nghĩa hằng số địa phương

ví dụ

localparam idle = 2’b00; // idle state of state machine localparam conv = 2’b01; // in this

state while A2D converting localparam accum = 2’b10; // in this state while averaging samples

3.3.3.5 parameter

có thể thay đổi khi tổng hợp mach

đề cập sau

3.4 3.4. Các mô hình mô tả mạch

3.4.1 3.4.1. Mô hình cấu trúc

3.4.1.1 Kết nối các phần tử cơ bản và các module con

3.4.1.2 Mô tả dạng text của mạng module gồm

Đường kết nối các phần tử trong mạch

Các phần tử trong mạch

Phần tử logic cơ bản

Flip-flop

Các module con

3.4.1.3 Các bước tạo mô hình cấu trúc

B1: Khai báo giao diện module

Tên module

Tên cổng, kiểu và kích thước cổng

B2: Khai báo các dây dẫn bên trong mạch

dùng kiểu biến wire

B3: Tạo module con hoặc primitive. Kết nối - đưa tên dây dẫn vào vị trí đầu vào, ra tương

ứng của cổng

Cú pháp

module_name instance_name [#(parameter values)] (port_connection_list)

port_connection_list

Phương pháp kết nối ẩn: dựa vào thứ tự khai báo cổng. Thứ tự tín hiệu khi tạo module

con quyết định cổng của module mà tín hiệu được nối vào.

Chỉ phù hợp với module ít cổng

Các cổng vào của module là giống nhau về vai trò (ví dụ primitive)

Khi số cổng lớn, dễ nhầm lẫn

Ví dụ

3.4.1.3..1.1.1.1 module dec_2_4_en (A, E_n, D); input [1:0] A; input E_n; output [3:0] D; . . .

3.4.1.3..1.1.1.2 wire [1:0] X; wire W_n; wire [3:0] word; // instantiate decoder dec_2_4_en DX (X, W_n,

word);

Phương pháp kết nối rõ ràng: chỉ rõ tên cổng mà tín hiệu sẽ được kết nối.

Cú pháp: .<port name>(<signal name>)

Ví dụ

3.4.1.3..1.1.1.3 wire [1:0] X; wire W_n; wire [3:0] word; // instantiate decoder dec_2_4_en DX (.A(X),

.E_n(W_n), .D(word));

3.4.1.4 Các cổng logic cơ bản (primitive)

Gate level

and, nand

or, nor

xor, xnor

buf , not

bufif0, bufif1, notif0, notif1 (three-state)

Switch level

*mos where * is n, p, c, rn, rp, rc; pullup, pulldown; *tran+ where * is (null), r and + (null), if0,

if1 with both * and + not (null)

Không cần khai báo, chỉ sử dụng (instantiate)

Khi sử dụng: đầu ra đứng đầu tiên, trước các đầu vào

Example: and N25 (Z, A, B, C); //instance name Example: and #10 (Z, A, B, X); // delay

(X, C, D, E); //delay /*Usually better to provide instance name for debugging.*/ Example: or N30

(SET, Q1, AB, N5), N41 (N25, ABC, R1); Example: and #10 N33(Z, A, B, X); // name + delay

3.4.1.5 Ví dụ

Ví dụ 3.4.1

module majority (major, V1, V2, V3) ; output major ; input V1, V2, V3 ; wire N1, N2, N3; and A0

(N1, V1, V2), A1 (N2, V2, V3), A2 (N3, V3, V1); or Or0 (major, N1, N2, N3); endmodule

Ví dụ 3.4.2

module half_add (X, Y, S, C); input X, Y ; output S, C ; xor SUM (S, X, Y); and CARRY (C, X, Y);

endmodule

module full_add (A, B, CI, S, CO) ; input A, B, CI ; output S, CO ; wire S1, C1, C2; // build full

adder from 2 half-adders half_add PARTSUM (A, B, S1, C1), SUM (S1, CI, S, C2); // … add an OR

gate for the carry or CARRY (CO, C2, C1); endmodule

Ví dụ 3.4.3

* module_keyword module_identifier (list of ports) */ module C_2_4_decoder_with_enable (A,

E_n, D) ; input [1:0] A ; // input_declaration input E_n ; // input_declaration output [3:0] D ; //

output_declaration assign D = {4{~E_n}} & ((A == 2'b00) ? 4'b0001 : (A == 2'b01) ? 4'b0010 :

(A == 2'b10) ? 4'b0100 : (A == 2'b11) ? 4'b1000 : 4'bxxxx) ; // continuous_assign endmodule

module C_4_16_decoder_with_enable (A, E_n, D) ; input [3:0] A ; input E_n ; output [15:0] D ;

wire [3:0] S; wire [3:0] S_n; C_2_4_decoder_with_enable DE (A[3:2], E_n, S); not N0 (S_n, S);

C_2_4_decoder_with_enable D0 (A[1:0], S_n[0], D[3:0]); C_2_4_decoder_with_enable D1 (A[1:0],

S_n[1], D[7:4]); C_2_4_decoder_with_enable D2 (A[1:0], S_n[2], D[11:8]); C_2_4_decoder_with_enable

D3 (A[1:0], S_n[3], D[15:12]); endmodule

3.4.1.6 Bài tập

Viết mô hình cấu trúc của mạch cộng 16bit CRA và CLA sử dụng bộ cộng full-adder

Tạo ra 20 giá trị đầu vào cho a, b

Mô phỏng timing cho 2 mạch

Đo độ trễ tpd cho từng giá tri đầu vào

Tính độ trễ trung bình cho 2 mạch CRA và CLA, so sánh

3.4.2 3.4.2. Mô hình dòng dữ liệu - RTL

3.4.2.1 Mô tả dòng xử lý dữ liệu

Dùng câu lệnh gán liên tục

assign

gán biểu thức bool cho biến wire

các phép gán assign hoạt động song song với nhau

phép gán sẽ được thực hiện khi giá trị biểu thức bên phải thay đổi

Mô hình chính xác, nhưng vẫn dễ đọc hiểu

Dùng mô tả các hàm Bool và đường dữ liệu

Nhược điểm: phải dựa vào phần mềm tổng hợp để tạo ra mạch

Với cách mạch yêu cầu tốc độ rất cao (GHz), vẫn cần mô hình cấu trúc

3.4.2.2 Ví dụ 3.4.3

module majority (major, V1, V2, V3) ; output major ; input V1, V2, V3 ; assign major = V1 &

V2 | V2 & V3 | V1 & V3; endmodule

3.4.2.3 Ví dụ 3.4.4

module fa_rtl (A, B, CI, S, CO) ; input A, B, CI ; output S, CO ; // use continuous assignments

assign S = A ^ B ^ CI; assign C0 = (A & B) | (A & CI) | (B & CI); endmodule

3.4.3 3.4.3. Mô hình hành vi

3.4.3.1 Mô tả các hành vi của mạch khi có các sự kiện (tín hiệu thay đổi giá trị) xảy ra

Dùng các khối always và initial

3.4.3.2 Ví dụ 3.4.5

module majority (major, V1, V2, V3) ; output reg major ; input V1, V2, V3 ; always @(V1, V2,

V3) begin if (V1 && V2 || V2 && V3 || V1 && V3) major = 1; else major = 0; end

endmodule

Trong mô phỏng: khi có sự thay đổi của V1, V2, hay V3 thì major sẽ được tính lại

Trong phần cứng: không có chờ đợi sự xuất hiện sự thay đổi=> các cổng logic tính toán ngay

lập tức

3.4.3.3 Ví dụ 3.4.6

module fa_bhv (A, B, CI, S, CO) ; input A, B, CI; output S, CO; reg S, CO; // assignment

made in an always block // must be made to registers // use procedural assignments

always@(A or B or CI) begin S = A ^ B ^ CI; CO = (A & B) | (A & CI) | (B & CI); end

endmodule

3.4.3.4 Chú ý

Khi mô phỏng khi tín hiệu đầu vào (bên phải phép gán) thay đổi, đầu ra (bên trái phép gán)

được tính toán lại

3.4.4 3.4.4. Phân cấp

3.4.4.1 Trong Verilog, mỗi khối (mạch) là một module.

3.4.4.2 Các module có thể được tái sử dụng bên trong một module khác (instantiate)

3.4.4.3 Thiết kế phân cấp xây dựng hệ thống từ các phần tử nhỏ hơn. Đây là phương pháp

thiết kế top-down

Primitives (cổng logic cơ bản)

Các module khác

3.4.4.4 Ví dụ

Thiết kế phân cấp của full-adder

Half-Adder

module Add_half(c_out, sum, a, b); output sum, c_out; input a, b; xor sum_bit(sum, a, b); and

carry_bit(c_out, a, b); endmodule

Full-Adder

module Add_full(c_out, sum, a, b, c_in) ; output sum, c_out; input a, b, c_in; wire w1, w2, w3;

Add_half AH1(.sum(w1), .c_out(w2), .a(a), .b(b)); Add_half AH2(.sum(sum), .c_out(w3), .a(c_in),

.b(w1)); or carry_bit(c_out, w2, w3); endmodule

3.4.4.5 Chú ý: Trong một module có thể sử dụng nhiều loại mô hình mô tả

Khi tổng hợp thành mạch, việc tính toán không cần chờ đợi được kích hoạt. Tính toán đồng

thời, cả 3 loại mô hình đều được tổng hợp thành phần cứng như nhau

3.4.4.6 Chú ý: Phạm vi của tín hiệu

Module cha không thể truy cập vào các tín hiệu trong module con => cần phải đưa ra thành

các cổng của module con

Ví dụ

module add8bit(cout, sum, a, b); output [7:0] sum; output cout; input [7:0] a, b;

wire cout0, cout1,… cout6; FA A0(cout0, sum[0], a[0], b[0], 1’b0); FA A1(cout1, sum[1], a[1],

b[1], cout0); … FA A7(cout, sum[7], a[7], b[7], cout6); endmodule

Để phát hiện tràn overflow = cout XOR cout6 Cần đưa ra tín hiệu cout6 hoặc overflow

3.4.4.7 Chú ý: Mỗi module nên đưa vào 1 file riêng biệt

Dễ tổ chức

Dễ tìm kiếm

Dễ tái sử dụng trong project khác

Tăng tốc độ tổng hợp khi tái sử dụng

Hình vẽ

Các module cùng trong 1 file

Mỗi module trong 1 file

3.5 3.5. Các cấu trúc mô tả dòng dữ liệu

3.5.1 3.5.1. Phép gán liên tục (continuous assignment)

3.5.1.1 Cú pháp

assign [drive_strength] [delay] list_of_net_assignments; Where: list_of_net_assignment ::=

net_assignment [{,net_assignment}] & Where: Net_assignment ::= net_lvalue = expression

assign <LHS> = <RHS expression>;

Khi các biến trong vế phải thay đổi giá trị, kết quả biểu thức RHS thay đổi, biến LHS được cập

nhật giá trị mới

Phép gán này hoạt động liên tục (hardware) và được tổng hợp thành mạch logic tổ hợp

Chú ý có một trường hợp ngoại lệ

Biểu thức RHS sử dụng các biến (dây dẫn, thanh ghi) và các phép toán: +,-,&,|,^,~,>>,…

LHS luôn là các biến kiểu dây dẫn (wire) hoặc phép toán nối vector

3.5.1.2 Ví dụ 3.5.1: Đơn giản

// out is a net, a & b are also nets assign out = a & b; // and gate functionality

3.5.1.3 Ví dụ 3.5.2: Gán vector

wire [15:0] result, src1, src2; // 3 16-bit wide vectors assign result = src1 ^ src2; // 16-bit

wide XOR

3.5.1.4 Ví dụ 3.5.3: Bộ cộng 32 bit

wire [31:0] sum, src1, src2; // 3 32-bit wide vectors assign {c_out,sum} = src1 + src2 + c_in;

// wow!

3.5.2 3.5.2. Các phép toán

3.5.2.1 Nối các vector

Tạo ra các vector từ các vector nhỏ hơn hoặc từ biến đơn

Operator {v1, v2}

Cú pháp: {list_of_subvector}

Các vector phía trái của danh sách các vector con sẽ có ý nghĩa cao hơn các vector phía phải

Ví dụ 3.5.4

module concatenate(out, a, b, c, d); input [2:0] a; input [1:0] b, c; input d; output

[9:0] out; assign out = {a[1:0],b,c,d,a[2]}; // assign out10 ={a[1:0],b,c,d,a[2]}[1:0]; endmodule

Ví dụ 3.5.5: Sử dụng khi kết nối cổng module

module add_concatenate(out, a, b, c, d); input [7:0] a; input [4:0] b; input [1:0] c;

input d; output [7:0] out; add8bit(.sum(out), .cout(), .a(a), .b({b,c,d}), .cin()); // đầu vào 8 bit b

của bộ cộng là 1 vector ghép từ 3 vector b, c, d endmodule

Thêm hằng số vào trước phép toán {}

Dùng để nhân bản bit

Ví dụ 3.5.6: Mở rộng dấu

input [7:0] offset; // 8-bit offset term from EEPROM wire [15:0] src1,src2; // 16-bit

source busses to ALU assign src1 = {8{offset[7]},offset}; // sign extend offset term // src1 =

offset[7], offset[7], ..., offset[7], offset[7], offset[6], ..., offset[0]

Chú ý phép toán tách vector là [msb_index:lst_index]

Ví dụ a[1:0] lấy 2 bit thấp của vector a

3.5.2.2 Phép toán số học

* multiply ** exponent / divide % modulus + add - subtract

Dễ mô tả hơn dùng mô hình cấu trúc

Không phải tất cả các phép toàn đều có thể tổng hợp

Ví dụ: các phép toàn *, **, /, % khó tổng hợp thành mạch logic, cho mạch kích thước lớn, tốc độ

chậm

Phần mềm tổng hợp thường sử dụng thư viện module có sẵn cho các phép toán

Cần chú ý đến kích thước kết quả

Ảnh hưởng đến dấu của phép toán

Kích thước (bitsize) quyết định bởi cả 2 phía của phép toán

Ví dụ 3.5.7: Các phép toán số học

1 module arithmetic_operators(); 2 3 initial begin 4 $display (" 5 + 10 = %d", 5 + 10); 5

$display (" 5 - 10 = %d", 5 - 10); 6 $display (" 10 - 5 = %d", 10 - 5); 7 $display (" 10 * 5 = %d", 10

* 5); 8 $display (" 10 / 5 = %d", 10 / 5); 9 $display (" 10 / -5 = %d", 10 / -5); 10 $display (" 10 %s

3 = %d","%", 10 % 3); 11 $display (" +5 = %d", +5); 12 $display (" -5 = %d", -5); 13 #10

$finish; 14 end 15 16 endmodule

3.5.2.3 Phép toán logic

Phép dịch

Dịch trái

Số học: <<<

Logic: <<

Dịch phải

Số học: >>>

Logic: >>

Ví dụ 3.5.8: Phép dịch

1 module shift_operators(); 2 3 initial begin 4 // Left Shift 5 $display (" 4'b1001

<< 1 = %b", (4'b1001 << 1)); 6 $display (" 4'b10x1 << 1 = %b", (4'b10x1 << 1)); 7 $display

(" 4'b10z1 << 1 = %b", (4'b10z1 << 1)); 8 // Right Shift 9 $display (" 4'b1001 >> 1 = %b",

(4'b1001 >> 1)); 10 $display (" 4'b10x1 >> 1 = %b", (4'b10x1 >> 1)); 11 $display (" 4'b10z1

>> 1 = %b", (4'b10z1 >> 1)); 12 #10 $finish; 13 end 14 15 endmodule

Phép so sánh

Lớn hơn, nhỏ hơn: <, >, <=, >=

Bằng: ==, !=

Có xét đến giá trị x và z

===, !==

chỉ dùng khi mô phỏng

Ví dụ 3.5.9: Phép so sánh

1 module relational_operators(); 2 3 initial begin 4 $display (" 5 <= 10 = %b", (5

<= 10)); 5 $display (" 5 >= 10 = %b", (5 >= 10)); 6 $display (" 1'bx <= 10 = %b", (1'bx

<= 10)); 7 $display (" 1'bz <= 10 = %b", (1'bz <= 10)); 8 #10 $finish; 9 end 10 11

endmodule

Ví dụ 3.5.10: Phép so sánh bằng

1 module equality_operators(); 2 3 initial begin 4 // Case Equality 5 $display ("

4'bx001 === 4'bx001 = %b", (4'bx001 === 4'bx001)); 6 $display (" 4'bx0x1 === 4'bx001 =

%b", (4'bx0x1 === 4'bx001)); 7 $display (" 4'bz0x1 === 4'bz0x1 = %b", (4'bz0x1 ===

4'bz0x1)); 8 $display (" 4'bz0x1 === 4'bz001 = %b", (4'bz0x1 === 4'bz001)); 9 // Case

Inequality 10 $display (" 4'bx0x1 !== 4'bx001 = %b", (4'bx0x1 ! == 4'bx001)); 11 $display ("

4'bz0x1 !== 4'bz001 = %b", (4'bz0x1 ! == 4'bz001)); 12 // Logical Equality 13 $display ("

5 == 10 = %b", (5 == 10)); 14 $display (" 5 == 5 = %b", (5 == 5)); 15 //

Logical Inequality 16 $display (" 5 != 5 = %b", (5 ! = 5)); 17 $display (" 5 != 6

= %b", (5 ! = 6)); 18 #10 $finish; 19 end 20 21 endmodule

Phép logic điều kiện

and: &&

or: ||

not: !

Dùng trong biểu thức điều kiện. Trả về kết quả là 1 bit

Ví dụ 3.5.11: Logic điều kiện

1 module logical_operators(); 2 3 initial begin 4 // Logical AND 5 $display ("1'b1

&& 1'b1 = %b", (1'b1 && 1'b1)); 6 $display ("1'b1 && 1'b0 = %b", (1'b1 && 1'b0)); 7

$display ("1'b1 && 1'bx = %b", (1'b1 && 1'bx)); 8 // Logical OR 9 $display ("1'b1 || 1'b0 =

%b", (1'b1 || 1'b0)); 10 $display ("1'b0 || 1'b0 = %b", (1'b0 || 1'b0)); 11 $display ("1'b0 ||

1'bx = %b", (1'b0 || 1'bx)); 12 // Logical Negation 13 $display ("! 1'b1 = %b", ( ! 1'b1));

14 $display ("! 1'b0 = %b", ( ! 1'b0)); 15 #10 $finish; 16 end 17 18 endmodule

Phép toán Bool

and: &

or: |

xor: ^

not: ~

Tính toán từng bit của vector. Kết quả là vector

Ví dụ 3.5.12: Phép toán Bool

1 module bitwise_operators(); 2 3 initial begin 4 // Bit Wise Negation 5 $display

(" ~4'b0001 = %b", (~4'b0001)); 6 $display (" ~4'bx001 = %b", (~4'bx001)); 7

$display (" ~4'bz001 = %b", (~4'bz001)); 8 // Bit Wise AND 9 $display (" 4'b0001 &

4'b1001 = %b", (4'b0001 & 4'b1001)); 10 $display (" 4'b1001 & 4'bx001 = %b", (4'b1001 &

4'bx001)); 11 $display (" 4'b1001 & 4'bz001 = %b", (4'b1001 & 4'bz001)); 12 // Bit Wise

OR 13 $display (" 4'b0001 | 4'b1001 = %b", (4'b0001 | 4'b1001)); 14 $display (" 4'b0001 |

4'bx001 = %b", (4'b0001 | 4'bx001)); 15 $display (" 4'b0001 | 4'bz001 = %b", (4'b0001 |

4'bz001)); 16 // Bit Wise XOR 17 $display (" 4'b0001 ^ 4'b1001 = %b", (4'b0001 ^

4'b1001)); 18 $display (" 4'b0001 ^ 4'bx001 = %b", (4'b0001 ^ 4'bx001)); 19 $display ("

4'b0001 ^ 4'bz001 = %b", (4'b0001 ^ 4'bz001)); 20 // Bit Wise XNOR 21 $display ("

4'b0001 ~^ 4'b1001 = %b", (4'b0001 ~^ 4'b1001)); 22 $display (" 4'b0001 ~^ 4'bx001 = %b",

(4'b0001 ~^ 4'bx001)); 23 $display (" 4'b0001 ~^ 4'bz001 = %b", (4'b0001 ~^ 4'bz001)); 24

#10 $finish; 25 end 26 27 endmodule

Phép rút gọn bit

Phép toán 1 số hạng. Thực hiện phép toán Bool với các toán hạng là các bit của vector, trả về

kết quả là 1 bit

and: &

nand: ~&

or: |

nor: ~|

xor: ^

Ví dụ 3.5.13: Phép toán rút gọn bit

1 module reduction_operators(); 2 3 initial begin 4 // Bit Wise AND reduction 5

$display (" & 4'b1001 = %b", (& 4'b1001)); 6 $display (" & 4'bx111 = %b", (& 4'bx111)); 7

$display (" & 4'bz111 = %b", (& 4'bz111)); 8 // Bit Wise NAND reduction 9 $display (" ~&

4'b1001 = %b", (~& 4'b1001)); 10 $display (" ~& 4'bx001 = %b", (~& 4'bx001)); 11 $display

(" ~& 4'bz001 = %b", (~& 4'bz001)); 12 // Bit Wise OR reduction 13 $display (" | 4'b1001 =

%b", (| 4'b1001)); 14 $display (" | 4'bx000 = %b", (| 4'bx000)); 15 $display (" | 4'bz000 =

%b", (| 4'bz000)); 16 // Bit Wise NOR reduction 17 $display (" ~| 4'b1001 = %b", (~|

4'b1001)); 18 $display (" ~| 4'bx001 = %b", (~| 4'bx001)); 19 $display (" ~| 4'bz001 = %b",

(~| 4'bz001)); 20 // Bit Wise XOR reduction 21 $display (" ^ 4'b1001 = %b", (^ 4'b1001));

22 $display (" ^ 4'bx001 = %b", (^ 4'bx001)); 23 $display (" ^ 4'bz001 = %b", (^ 4'bz001));

24 // Bit Wise XNOR 25 $display (" ~^ 4'b1001 = %b", (~^ 4'b1001)); 26 $display (" ~^

4'bx001 = %b", (~^ 4'bx001)); 27 $display (" ~^ 4'bz001 = %b", (~^ 4'bz001)); 28 #10

$finish; 29 end 30 31 endmodule

3.5.2.4 Phép toán điều kiện

Cú pháp

cond_expr ? true_expr : false_expr

Ví dụ 3.5.14: Phép toán có điều kiện

1 module conditional_operator(); 2 3 wire out; 4 reg enable,data; 5 // Tri state buffer 6

assign out = (enable) ? data : 1'bz; 7 8 initial begin 9 $display ("time\t enable data out"); 10

$monitor ("%g\t %b %b %b",$time,enable,data,out); 11 enable = 0; 12 data = 0; 13 #1 data =

1; 14 #1 data = 0; 15 #1 enable = 1; 16 #1 data = 1; 17 #1 data = 0; 18 #1 enable = 0; 19

#10 $finish; 20 end 21 22 endmodule

Chú ý khi mô tả latch?

assign q_out = enable ? data_in : q_out;

Kết quả tổng hợp

Chú ý: Luôn luôn cần biết mã Verilog được tổng hợp thành mạch cứng như thế nào?

3.5.2.5 Thứ tự ưu tiên của các phép toán

Unary, Multiply, Divide, Modulus !, ~, *, /, % Add, Subtract, Shift +, - , <<, >> Relation,

Equality <,>,<=,>=,==,!=,===,!== Reduction &, !&,^,^~,|,~| Logic &&, || Conditional ? :

3.5.2.6 Bài tập

3.5.1.Tổng hợp các phép toán bằng quartus

Xác định các phép toán hỗ trợ bởi quartus

So sánh kích thước (LE) khi tổng hợp các phép toán

So sánh kích thước với bộ cộng CRA, CLA mô tả bằng mô hình cấu trúc với phép cộng

So sánh độ trễ CRA, CLA với phép cộng

3.5.2. Xây dựng khối ALU 32 bit

Đầu vào

opA: 32 bit

opB: 32 bit

shamt: 5 bit

func

= 0: cộng

=1: trừ

=2: nhân

=3: so sánh bằng

=4: dịch trái số học opA số bit mã hóa trong shamt

=5: dịch phải số học opA số bit mã hóa trong số shamt

=others: đầu ra = 0000

Đầu ra

res: 32 bit

overflow

zero=1: nếu so sánh bằng nhau

a) Khi chưa có phép nhân xác định số LE và tốc độ

b) Thêm phép nhân xác định số LE và tốc độ

c) Mô phỏng để kiểm tra kết quả với ít nhất 5 cặp số opA, opB cho mỗi phép toán

3.6 3.6. Các cấu trúc mô tả hành vi

3.6.1 3.6.1. Một số khái niệm chung

3.6.1.1 Cấu trúc always/initial dùng để mô hình hoạt động dạng hành vi của mạch

3.6.1.2 Tất cả các cấu trúc hành vi khác đều nằm trong 2 khối always/initial

3.6.1.3 Nhiều cấu trúc hành vi có thể nằm trong always/initial bằng cách đặt giữa begin và

end

3.6.1.4 Tất cả các biến ở bên trái phép gán trong 2 khối always/initial đều phải là kiểu reg

3.6.2 3.6.2. Cấu trúc initial

3.6.2.1 Bắt đầu thực hiện ở thời điểm mô phỏng 0

3.6.2.2 Có thể có nhiều cấu trúc initial trong mã, chúng được thực hiện độc lập và đều bắt

đầu thực hiện ở thời điểm 0

3.6.2.3 Không được tổng hợp thành mạch

3.6.2.4 Các câu lệnh trong khối initial được thực hiện lần lượt và được thực hiện 1 lần

3.6.2.5 Chủ yếu được dùng trong testbench

3.6.2.6 Chú ý: Không dùng initial trong mô tả mạch

3.6.2.7 Ví dụ 3.6.1: Dùng cấu trúc initial trong testbench

`timescale 1 ns / 100 fs module full_adder_tb; reg [3:0] stim; wire s, c; full_adder(sum,

carry, stim[2], stim[1], stim[0]); // instantiate DUT // monitor statement is special - only needs to

be made once, initial $monitor(“%t: s=%b c=%b stim=%b”, $time, s, c, stim[2:0]); // tell our

simulation when to stop initial #50 $stop; initial begin // stimulus generation for (stim = 4’h0;

stim < 4’h8; stim = stim + 1) begin #5; end end endmodule

3.6.2.8 Cú pháp

initial [begin] behavior_statements; [end]

3.6.3 3.6.3. Cấu trúc always

3.6.3.1 Bắt đầu ở thực hiện ở thời điểm 0

3.6.3.2 Được thực hiện lặp đi lặp lại liên tục khi có sự kiện xảy ra trong danh sách kích hoạt

(trigger_list, danh sách nhậy - sensitive list)

3.6.3.3 Ví dụ 3.6.2: always 1

module clock_gen (output reg clock); initial clock = 1’b0; // must initialize in initial block

always // no trigger list for this always #10 clock = ~clock; // always will re-evaluate when //

last <LHS> assignment completes endmodule

3.6.3.4 Chú ý mô tả hoạt động của mạch

Tổ hợp

Không dùng kích hoạt bằng sườn (edge-triggered)

Tất cả các "đầu vào" (biến ở vế phải phép gán) cần được đưa vào trigger-list

Không phụ thuộc đồng hồ

Tuần tự (dãy)

Sự kiện đồng hồ và mô tả Flip-Flop

Sự kiện đồng hồ

posedge

3.6.3.4..1.1.1.1 Xảy ra khi tín hiệu chuyển từ 0 lên x,z, 1

3.6.3.4..1.1.1.2 Xảy ra khi tín hiệu chuyển tử x, z lên 1

negedge

3.6.3.4..1.1.1.3 Xảy ra khi tín hiệu chuyển từ 1 xuống x,z, 0

3.6.3.4..1.1.1.4 Xảy ra khi tín hiệu chuyển tử x, z xuống 0

Sử dụng sự kiện đồng hồ để mô tả Flip-Flop

always @ (posedge clk) register <= register_input;

Ví dụ 3.6.3: Mô tả D-FF không có tín hiệu reset

reg q; always @(posedge clk) q <= d;

Kết quả tổng hợp

3.6.3.4..1.1.1.5

Chú ý: Không nên dùng FF không có reset

Ví dụ 3.6.4: Mô tả D-FF có reset đồng bộ

reg q; always @(posedge clk) if (!rst_n) q <= 1’b0; //synch reset else q <= d;

Kết quả tổng hợp

3.6.3.4..1.1.1.6

Tín hiệu reset không nằm trong danh sách kích hoạt của khối always

Ví dụ 3.6.5: Mô tả flip-flop với reset không đồng bộ

Kết quả tổng hợp

3.6.3.4..1.1.1.7 Thư viện các cổng thường có flip-flop với đầu vào reset không đồng bộ

3.6.3.4..1.1.1.8 Kích thước lớn hơn flipflop thường không đáng kể

3.6.3.4..1.1.1.9

reg q; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1’b0; //synch reset

else q <= d;

Tín hiệu reset nằm trong trigger list của khối always

Ví dụ 3.6.6: Mô tả flip-flop với reset đồng bộ/không đồng bô và tín hiệu enable

Mã reset đồng bộ

3.6.3.4..1.1.1.10 1 module always_example(); 2 reg clk,reset,enable,q_in,data; 3 4 always @ (posedge clk)

5 if (reset) begin 6 data <= 0; 7 end else if (enable) begin 8 data <= q_in; 9 end 10 11 endmodule

3.6.3.4..1.1.1.11 Kết quả tổng hợp

3.6.3.4..1.1.1.12

Mã reset không đồng bộ

Chú ý: Cần biết rõ các cổng có trong thư viện

FF điều khiển bởi sườn dương hay sườn âm?

Đầu vào reset là active low hay active high, đồng bộ hay không đồng bộ?

FF có hỗ trợ test?

Khi viết code, viết code cho những cổng có trong thư viện

3.6.3.4..1.1.1.13 Phần mềm tổng hợp sẽ tạo ra mạch kích thước nhỏ nhất (cần ít cổng logic nhất)

3.6.3.4..1.1.1.14 Nếu thư viện không có FF với reset active high=>viết code thế nào?

Kích hoạt bằng sườn của tín hiệu đồng hồ

Chỉ đồng hồ và reset nằm trong trigger-list

Có thể bao gồm phần mô tả mạch tổ hợp nối vào FF. Tức là mô tả hàm trạng thái kế tiếp của

FF.

Ví dụ 3.6.7: Kết hợp logic tổ hợp trong khối always mạch dãy

module counter(up,down, cnt, rst_n, clk); output [7:0] cnt; input up,down; // =

10 count up, 01 count down, otherwise stop input clk, rst_n; reg [7:0] cnt; always @

(posedge clk or negedge rst_n) if (!rst_n) cnt <= 0; else if (up) cnt <= cnt+1;

else if (down) cnt <= cnt-1; else cnt <= cnt; endmodule

3.6.3.5 Cú pháp

always @(trigger list) begin behavior_statements; end

Trigger list (sensitive list)

always @(a, b, c) begin … end

Cú pháp

Before Verilog 2001

always @(signal_1 or signal_2 or signal 3 or...)

Verilog 2001

always @(signal_1, signal_2, signal_3, ...)

always @(*)

3.6.3.5..1.1.1.1 Dùng để mô tả mạch logic tổ hợp

3.6.3.5..1.1.1.2 Không khuyên dùng

Kích hoạt việc thực hiện các lệnh trong khối always khi có sự thay đổi giá trị của các tín hiệu

trong list

Nếu không có danh sách kích hoạt, được thực hiện lặp lại ngay sau khi phép gán cuối cùng kết

thúc

Chú ý: chỉ dùng trong testbench và mô phỏng

Các tín hiệu xuất hiện trong trigger list là đầu vào của khối mạch tổ hợp được mô tả bằng cấu

trúc always

Các tín hiệu cần xuất hiện trong trigger list là các biến/tín hiệu ở biểu thức bên phải phép gán

trong khối always

3.6.4 3.6.4. Phép gán blocking và non-blocking

3.6.4.1 Lệnh gán tuần tự (Blocking Assignment)

Cú pháp

LHS = RHS

LHS: các biến kiểu reg hoặc biểu thức nối vector của các biến kiểu reg

RHS: biểu thức

Trong mô phỏng được thực hiện tuần tự từng phép gán

B1: Tính toán RHS

B2: Gán RHS vào LHS

Trong tổng hợp: mô tả cổng logic trong mạch logic tổ hợp. Thể hiện sự kết nối tuần tự của

các cổng logic (đầu ra tới đầu vào)

Chú ý: Chỉ khi kết quả của phép gán phía trước được sử dụng trong phép gán phía sau

Ví dụ 3.6.8: Lệnh gán tuần tự

module addtree(output reg [9:0] out, input [7:0] in1, in2, in3, in4); reg [8:0] part1, part2;

always @(in1, in2, in3, in4) begin part1 = in1 + in2; part2 = in3 + in4; out = part1 + part2; end

endmodule

Kết quả tổng hợp

3.6.4.2 Lệnh gán song song (Nonblocking assignment)

Cú pháp

LHS <= RHS

LHS: các biến kiểu reg hoặc biểu thức nối vector

RHS: biểu thức

Trong mô phỏng được thực hiện đồng thời nếu không có thêm giá trị trễ

B1: Tính toán RHS cho tất cả các phép gán

B2: Gán RHS của từng biểu thức cho LHS tương ứng theo thứ tự không xác định

Trong tổng hợp: mô tả thanh ghi trong mạch tuần tự (dãy). Thể hiện các FF độc lập (giá trị

hiện tại của các FF không phụ thuôc vào nhau)

Ví dụ 3.6.9: Lệnh gán song song

module swap(output reg out0, out1, input rst, clk); always @(posedge clk) begin if (rst) begin

out0 <= 1’b0; out1 <= 1’b1; end else begin out0 <= out1; out1 <= out0; end end endmodule

Kết quả tổng hợp

3.6.4.3 So sánh gán tuần tự và gán song song

Ví dụ 3.6.10:Swap dùng lệnh gán tuần tự

module swap(output reg [15:0] out0, out1, input [15:0] in0, in1, input swap); reg [15:0] temp;

always @(*) begin out0 = in0; out1 = in1; if (swap) begin temp = out0; out0 = out1; out1 = temp; end

end endmodule

Kết quả tổng hợp

Ví dụ 3.6.11: Không dùng lệnh gán tuần tự để mô tả mạch tuần tự (trong always)

Chú ý: Việc tính toán biểu thức vế phải của các câu lệnh phía sau lệnh gán tuần tự sẽ bị dừng

cho đến khi việc gán kết thúc

Mục tiêu mô tả mạch

module pipe(input clk, d, output q1, q2, q3);

Mã mô tả dùng lệnh gán tuần tự

module blocking_pipe(clk, d, q1, q2, q3); input clk,d; output q1, q2, q3; reg q1, q2, q3;

always @(posedge clk) begin q1 = d; q2 = q1; q3 = q2; end endmodule

Kết quả tổng hợp

Mã mô tả dùng lệnh gán song song

module blocking_pipe(clk, d, q1, q2, q3); input clk,d; output q1, q2, q3; reg q1, q2, q3;

always @(posedge clk) begin q1 <= d; q2 <= q1; q3 <= q2; end endmodule

Kết quả tổng hợp

Ví dụ 3.6.12: Không dùng lệnh gán song song để mô tả mạch logic tổ hợp

Mã 1

module nonblocking_comb(z,a,b,c,d); input a,b,c,d; output z; reg z,tmp1,tmp2; always

@(a,b,c,d) begin tmp1 <= a & b; tmp2 <= c & d; z <= tmp1 | tmp2; end endmodule

Testbench

module test_nonblocking_comb; reg a, b, c, d; wire z; nonblocking_comb

nonblocking_comb_dut(z, a, b, c, d); initial $monitor ("%g z=%b, a=%b, b=%b, c=%b,

d=%b", $time, z, a, b, c, d); initial begin #0 a = 0; #0 b = 1; #0 c = 0; #0 d = 1; #5 a =

1; #5 c = 1; #5 b = 0; #5 d = 0; end endmodule;

Kết quả mô phỏng

# 0 z=x, a=0, b=1, c=0, d=1 # 5 z=0, a=1, b=1, c=0, d=1 (kết quả mô phỏng sai vì z

được tính bằng giá trị cũ của tmp1, tmp2) # 10 z=1, a=1, b=1, c=1, d=1 # 15 z=1, a=1, b=0,

c=1, d=1 # 20 z=1, a=1, b=0, c=1, d=0

Timing diagram

3.6.4.3..1.1.1.1

Phân tích:

1) a, b, c, d thay đổi => khối always được tính lại. Tức là tính lại các biểu thức bên

phải phép gán với các giá trị mới của a, b, c, d và giá trị cũ của tmp1, tmp2

2) phép gán cho tmp1, tmp2 được và phép gán cho z được định thời gian thực hiện

3) Thực hiện phép gán cho tmp1, tmp2, z làm các biến này thay đổi giá trị

4) Kết thúc thực hiện khối always đợi sự thay đổi itếp theo của a, b, c, d

Chú ý: tmp1, tmp2 thay đổi không làm always được thực hiện

Mã 2

module nonblocking_comb(z,a,b,c,d); input a,b,c,d; output z; reg z,tmp1,tmp2; always

@(a,b,c,d, tmp1, tmp2) begin tmp1 <= a & b; tmp2 <= c & d; z <= tmp1 | tmp2; end

endmodule

Kết quả mô phỏng

run # 0 z=0, a=0, b=1, c=0, d=1 # 5 z=1, a=1, b=1, c=0, d=1 # 10 z=1, a=1, b=1, c=1,

d=1 # 15 z=1, a=1, b=0, c=1, d=1 # 20 z=0, a=1, b=0, c=1, d=0

Phân tích:

1) a, b, c, d thay đổi => khối always được tính lại. Tức là tính lại các biểu thức bên

phải phép gán với các giá trị mới của a, b, c, d và giá trị cũ của tmp1, tmp2

2) phép gán cho tmp1, tmp2 được và phép gán cho z được định thời gian thực hiện

3) Thực hiện phép gán cho tmp1, tmp2, z làm các biến này thay đổi giá trị

4) Khối always được tính toán lần thứ 2 do sự thay đổi của tmp1, tmp2

Kết quả tổng hợp

Mã 2 đúng nhưng sẽ mất thời gian mô phỏng hơn khi dùng lệnh gán tuần tự

Bài tập: Viết lại đoạn mã trên dùng phép gán blocking. Các tín hiệu nào cần nằm trong

trigger_list để kết quả mô phỏng đúng? Kết quả tổng hợp mạch như thế nào?

Tham khảo thêm: Clifford E. Cummings, "Nonblocking Assignments in Verilog Synthesis,

Coding Styles That Kill!"

3.6.5 3.6.5. Cấu trúc if-else

3.6.5.1 Cú pháp

if đơn

if (condition) begin <statement1>; <statement2>; end

if và else

if (condition) begin <statement1>; <statement2>; end else begin <statement3>;

<statement4>; end

nested if

if (condition) begin <statement1>; <statement2>; end else if (condition2) begin

<statement3>; <statement4>; end else begin <statement5>; <statement6>; end

3.6.5.2 Tổng hợp

Phần cứng cho tất cả các nhánhthực hiện qua khối if/else đều được tạo ra

Không tạo ra phần cứng phụ thuộc vào kết quả điều kiện

Các nhánh được tính toán đồng thời

Tạo ra các khối mux để lựa chọn kết quả

Kết quả được lựa chọn phụ thuộc điều kiện

3.6.5.3 Ví dụ 3.6.13. Lệnh if/else

if (func_add) alu = a + b; else if (func_and) alu = a & b; else alu = 8’h00;

Kết quả tổng hợp

Ứng với mỗi nhánh if, một khối tính toán tương ứng được tạo ra (+, &, 8'h00)

Bộ mux thứ nhất để lựa chọn nhánh if và else dưới cùng

Bộ mux thứ 2 để lựa chọn nhánh if và else phía trên

3.6.5.4 Chú ý phần tử latches ẩn

Khi if không đi kèm else tương ứng

Ví dụ 3.6.14. Lệnh if thiếu nhánh else

module if_no_else(input [1:0] alu_func, input [4:0] src1, src2, output reg [4:0] res);

parameter alu_add = 2'b00; parameter alu_and = 2'b01; always @(alu_func, src1, src2) begin

// tránh latch khi không có nhánh else, // nhưng không khuyến khích. res = 0; if (alu_func

== alu_add) begin res = src1 + src2; end else if (alu_func == alu_and) begin res = src1 & src2;

end end endmodule

Kết quả tổng hợp

Lý do

res là kiểu reg, nó sẽ giữ nguyên giá trị khi không được gán giá trị mới (i.e. khi

alu_func != alu_add, alu_and) => latch

Chú ý: Luôn có viết if có else

3.6.5.5 Chú ý mức ưu tiên khi tổng hợp các nhánh if

Ví dụ 3.6.15: if lồng nhau

module nested_if(input clk, rst_n, up_en, down_en, output reg [3:0] counter); always

@ (posedge clk or negedge rst_n) // If reset is asserted if (!rst_n) begin counter <= 4'b0000;

// If counter is enable and up count is asserted end else if (up_en) begin counter <= counter +

1'b1; // If counter is enable and down count is asserted end else if (down_en) begin counter

<= counter - 1'b1; // If counting is disabled end else begin counter <= counter; // Redundant

code end endmodule

Kết quả tổng hợp

Khi các nhánh if được lồng với nhau, nhánh if đầu tiên sẽ có mức ưu tiên cao nhất

Khi điều kiện của các nhánh if lồng nhau không loại trừ nhau (overlapped conditions - có thể

cùng đúng) thì kết quả mạch có thể khác với specification

Ví dụ

Mạch đếm tăng/giảm có đầu vào: up,down = 10 => đếm tăng up,down = 01 => đếm

giảm others => dừng

Cần viết các điều kiện của nhánh if loại trừ nhau

Nếu điều kiện các nhánh if không loại trừ

3.6.5.5..1.1.1.1 module counter(input clk, input rst_n, input up, down, output reg [7:0] cnt); always

@(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 0; else if (up) cnt <= cnt+1; else if (down) cnt <=

cnt-1; else cnt <= cnt; end endmodule

Hoạt động

3.6.5.5..1.1.1.2 updown=11 vẫn đếm tăng

3.6.6 3.6.6. Cấu trúc case

3.6.6.1 Cú pháp

case (expression) alternative1 : statement1; // any of these statements could alternative2

: statement2; // be a compound statement using alternative3 : statement3; // begin/end default :

statement4 // always use default for synth stuff endcase

so sánh từng bit của expression với case item (alternative1, 2, 3, ...)

Nếu expression bằng nhánh case nào, thì sẽ thực hiện câu lệnh trong nhánh case tương ứng

3.6.6.2 Các loại case

case

Phân biệt các giá trị x, z, 0, 1

Các chuỗi bít 01, 0x, z1 là khác nhau

Ví dụ 3.6.16: Normal case

module alu(input [1:0] alu_op, input [31:0] src1, src2, output reg [31:0] res);

parameter AND = 2'b00; parameter OR = 2'b01; parameter XOR = 2'b10; parameter ADD =

2'b11; always @(alu_op, src1, src2) begin case (alu_op) AND : res = src1 & src2; OR : res

= src1 | src2; XOR : res = src1 ^ src2; default : res = src1 + src2; endcase end endmodule

Kết quả tổng hợp

casez

Các bit có giá trị z, ? được coi như nhau là don't care: có thể match với 0/1

Các chuỗi 01, 00, 0z, 0? được coi là giống nhau

Ví dụ 3.6.18: casez

casex

Các bit có giá trị x, z, ? được coi như nhau là don't care có thể match 0/1

Khi có nhiều lựa chọn case (alternative) cùng phù hợp với expression thì sử dụng lựa chọn đầu

tiên => alternative phía trên có mức độ ưu tiên cao hơn

Ví dụ 3.6.17: casex

module test_casex(); reg [1:0] code; reg [7:0] control; always @ (code) begin casex

(code) // case expression 2'b0?: control = 1; // case item1 2'b10: control = 2; // case item

2 2'b11: control = 3; // case item 3 endcase end initial $monitor("%t: code = %b, control =

%d", $time, code, control); initial begin #0 code = 2'b00; #5 code = 2'b01; #5 code = 2'b10;

#5 code = 2'b11; #5 code = 2'b1x; #5 code = 2'b0x; end endmodule

Kết quả mô phỏng

3.6.6.3 Chú ý:

Để tránh latch thì luôn phải có nhanh default

Luôn viết case cho trường hợp các điều kiện alternative là loại trừ nhau và có mức độ ưu

tiên như nhau

Nếu muốn viết điều kiện có ưu tiên và không loại trừ thì nên dùng if lồng

Hạn chế dùng casez và casex

Tham khảo:Clifford Cummings: "full_case parallel_case, the Evil Twins of Verilog Synthesis"

3.7 3.7 Thực hành

3.7.1 Làm quen với phần mềm Altera Quartus

3.7.1.1 Mô phỏng mạch số

ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Tutorials/Verilog/Quartus_II_Simulatio

n.pdf

See document(s): Quartus_II_Simulation.pdf

3.7.1.2 Giới thiệu Quartus

ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Tutorials/Verilog/Quartus_II_Introducti

on.pdf

3.7.2 Làm quen với kit DE1

3.7.2.1 ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Tutorials/Getting_Started_with_

DE-series_boards.pdf

3.7.3 Bài Lab 1

3.7.3.1 ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Laboratory_Exercises/Digital_Lo

gic/DE2/verilog/lab1_Verilog.pdf

3.7.3.2 Chú ý trong bài lab này ta cần làm các bước

B1. Xác định bảng sự thật cho các đầu ra

B2. Tối giản các hàm Bool cho đầu ra

B3. Triển khai mô ta các hàm Bool đầu ra bằng câu lệnh gán assign trong Verilog. Hoặc mô tả

mạch bằng Verilog

3.7.4 Bài Lab 2

3.7.4.1 ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Laboratory_Exercises/Digital_Lo

gic/DE2/verilog/lab2_Verilog.pdf

3.7.4.2 Làm hết phần 2

3.7.5 Đỗ trễ

3.7.5.1 Cách mô tả độ trễ 1 cổng trong Verilog

3.7.5.2 Mô phỏng độ trễ của mạch trong lab1 và lab2

3.7.6 Tham khảo

3.7.6.1 altera.com, university program

3.8 Bài tập chương:

3.8.1 Thiết kế bộ đếm mã gray 4 bit, bộ dịch logic trái phải 1 bit, bộ quay trái phải 1 bit

gồm n bit

4 Chương 4. Mô phỏng và testbench

4.1 4.1. Nguyên tắc hoạt động của chương trình mô phỏng

4.1.1 4.1.1. Định nghĩa: Là quá trình phân tích mô hình mô tả mạch để tính toán giá trị

đầu ra từ đầu vào

4.1.1.1 Là một quá trình thực hiện trừu tượng bằng bộ não con người hoặc máy tính

4.1.2 4.1.2. Nguyên tắc mô phỏng mạch số

4.1.2.1 Khi đầu vào thay đổi tính toán lại toàn bộ các tín hiệu trong mạch

Hình vẽ

4.1.2.2 Khi dầu vào thay đổi tính lại các đường từ đầu vào

Hình vẽ

4.1.3 4.1.3. Mô phỏng dựa trên sự kiện

4.1.3.1 B1: Đưa các tín hiệu đầu vào thay đổi vào hàng đợi sự kiện tại thời gian mô phỏng 0

4.1.3.2 B2: Lặp lại đến khi nào hàng đợi rỗng

Lấy một tín hiệu ra khỏi hàng đợi

Với mỗi phần tử (cổng logic, câu lệnh Verilog, module, lệnh gán...) là fanout(sink) của tín

hiệu

Tính lại giá trị đầu ra tương ứng của phần tử

Nếu đầu ra thay đổi giá trị, đưa tín hiệu đầu ra vào hàng đợi tại thời điểm mô phỏng = thời

điểm hiện tại + trễ của phần từ

4.1.3.3 B3: Khi hàng đợi rỗng, giữ nguyên kết quả mô phỏng hoặc đi đến thời gian mô

phỏng tiếp theo

4.1.3.4 Hình vẽ

4.1.3.5 Ví dụ mô phỏng mạch số

4.1.3.6 Ưu điểm của mô phỏng sự kiện

Tốc độ nhanh

Mô phỏng được thời gian

Mô phỏng được mạch mô tả bằng các mô hình cấu trúc/RTL/hoạt động

4.1.4 4.1.4. Thời gian trong mô phỏng

4.1.4.1 Được dùng để mô hình hóa thời gian hoạt động của mạch (độ trễ tính toán)

Không trễ (zero-delay)

Cú pháp

and A0(OUT, A, B);

assign OUT = A&B;

always @(A, B) OUT = A&B;

Đầu ra được thay đổi cùng với đầu vào

Sự kiện tại OUT được đưa vào hàng đợi tại thời điểm mô phỏng hiện tai

Không thực tế

Có thể chấp nhận kết quả mô phỏng khi xét mạch hoạt động đồng bộ

Trễ đơn vị (unit-delay)

Các phần tử trong mạch được gán một thời gian trễ tính theo đơn vị trễ tưởng tượng

Không chính xác, nhưng là xấp xỉ gần đúng thực tế

Thể hiện được thực tế là số mức logic ảnh hưởng tới tốc độ của mạch

Dễ dàng quan sát sự thay đổi của tín hiệu lan truyền trong mạch

Cú pháp

and #1 A0(OUT, A, B);

assign OUT = #1 A & B; assign #1 OUT = A & B;

OUT được thay đổi 1 đơn vị mô phỏng sau khi A hoặc/và B thay đổi

Quy định đơn vị thời gian trong Verilog

`timescale 1ns /100 fs // time_unit/time_precision ' `

Tuy nhiên: Không nên viết độ trễ của cổng logic trong phần mô tả mạch

Vẫn không chính xác

Không có kết quả tổng hợp tương ứng

Chậm tốc độ mô phỏng

Có thể mô phỏng thời gian ngay sau khi tổng hợp

Chỉ nên dùng độ trễ trong testbench

4.1.4.2 Ví dụ về mô tả trễ trong Verilog

wire #5 net_1; // 5 unit trễ dây dẫn

and #4 (z_out, x_in, y_in); // 4 unit trễ cổng

wire #2 z_out; // 2 unit trễ dây dẫn

and #3 (z_out, x_in, y_in); // 3 for gate, 2 for wire

wire #3 c; // 3 unit transport delay

assign #5 c = a & b; // 5 for assign, 3 for wire

assign z_out = #3 a & b; // 3 unit trễ cổng

Thực hiện tính toán, chờ 3 đơn vị trễ và gán z_out = a & b

assign #3 z_out = a & b; // 3 unit trễ cổng

Thực hiện tính toán và gán z_out = a & b sau đó chờ 3 đơn vị trễ

Chỉ nên dùng kiểu trễ này

4.1.4.3 Trễ trong câu lệnh gán Verilog

Inter-Statement Delay

Trễ cả việc tính RHS và gán

#4 c = d; #8 e = f;

Intra-Statement Delay

Trễ việc gán nhưng không trễ việc tính RHS

c = #4 d; e = #8 f;

Ví dụ so sánh

# 0: a= 3, b= x # 3: a= 1, b= x # 6: a=

1, b= 2 # 8: a= 1, b= 3 # 10: a= 4, b= 3

# 0: a= 3, b= x # 3: a= 1, b= x # 6: a=

1, b= 6 # 8: a= 1, b= 3 # 10: a= 7, b= 3

Chú ý: Không gán giá trị cho một biến trong nhiều khối lệnh

4.2 4.2. Testbench

4.2.1 4.2.1. Định nghĩa

4.2.1.1 Mô hình hóa môi trường hoạt động của mạch cần được kiểm tra (DUT, DUV)

4.2.1.2 Là một module Verilog không có đầu vào và đầu ra

4.2.1.3 Hình vẽ

4.2.2 4.2.2. Chức năng

4.2.2.1 Tạo ra tín hiệu đầu vào (input vectors, input patterns, input stimuti) đưa tới mạch

cần kiểm tra

4.2.2.2 Theo dõi tín hiệu đầu ra (và) so sánh, kiểm tra với tín hiệu đầu ra chuẩn (đúng)

4.2.2.3 Ví dụ 4.2.1

Mạch cộng 4 bit

Testbench

`timescale 1ns /100 fs // time_unit/time_precision-định nghĩa đơn vị thời gian mô phỏng

module adder4bit_tb; // Khai báo các tín hiệu nối vào DUT reg[8:0] stim; // inputs to DUT are regs

wire[3:0] S; // outputs of DUT are wires wire C4; // instantiate DUT adder4bit adder4bit_DUT

(.sum(S), .c_out(C4), .a(stim[8:5]), .b(stim[4:1]), .c(stim[0])); // stimulus generation -- tạo tín hiệu đầu

vào initial begin stim = 9'b0000_0000_0; // at 0 ns #10 stim = 9'b1111_0000_1; // at 10 ns

#10 stim = 9'b0000_1111_1; // at 20 ns #10 stim = 9'b1111_0001_0; // at 30 ns #10 stim =

9'b0001_1111_0; // at 40 ns #10 $stop; // at 50 ns – stops simulation end // outputs observation

initial $monitor("%t, a = %d, b=%d, ci=%b, s = %d, co=%b", $time, stim[8:5], stim[4:1],stim[0],s, c4)

endmodule

4.2.2.4 Bài tập: Viết testbench cho bộ cộng 16 bit, CLA và CRA

4.2.3 4.2.3. Thành phần

4.2.3.1 1. Tạo module con là DUT và kết nối đầu vào của DUT với tín hiệu chứa input

patterns (mẫu đầu vào), kết nối đầu ra với tín hiệu được quan sát và kiểm tra

4.2.3.2 2. Tạo mẫu tín hiệu đầu vào cho DUT

Phương pháp 1: Tạo tất cả các tổ hợp tín hiệu đầu vào

Sử dụng vòng lặp

for (x = 0; x < 16; x = x + 1) #5;

Ví dụ 4.2.2

`timescale 1ns /100 fs // time_unit/time_precision module adder4bit_tb; reg [9:0]

stim; // inputs to DUT are regs - chú ý để vòng lặp for ở dưới kết thúc, stim có nhiều hơn 1

bit so với số bit đầu vào wire[3:0] S; // outputs of DUT are wires wire C4; // instantiate

DUT adder4bit(.sum(S), .c_out(C4), .a(stim[8:5]), .b(stim[4:1]), .c(stim[0])); // stimulus

generation initial begin for (stim = 0;stim <512; stim = stim+1) #10; #10 $stop; end

endmodule

exhaustive/complete simulation

Chậm

Không khả thi

Sử dụng cho các mạch nhỏ

Đảm bảo chắc chắn phát hiện được các lỗi của mạch

Phương pháp 2: Tạo tổ hợp tín hiệu đầu vào ngẫu nhiên

Sử dụng hàm random

Không phát hiện được tất cả các lỗi

Có thể bỏ sót các lỗi ở các trường hợp tới hạn/trường hợp góc (critical corner cases)

Bài tập: xây dựng lại testbench ở ví dụ trên dùng hàm random

Phương pháp 3: Tạo đầu vào từ các kịch bản hoạt động của mạch

Xem xét các trường hợp hoạt động tới hạn của mạch

Đầu vào và đầu ra tương ứng có thể được đọc ra từ file

Với mỗi mạch khác nhau sẽ cần liệt kê ra trường hợp tới hạn khác nhau

Được xác định trong bước lên kế hoạch kiểm tra (Verification Plan)

Được tiến hành đồng thời với bước Architecture Design

Phân tích các kịch bản hoạt động của mạch chính là tương ứng với phân tích/phân rã

chức năng của mạch

Tham số đánh giá chất lượng tổ hợp đầu vào

Coverage Metrics

Bao phủ mã

Bao phủ câu lệnh

Bao phủ điều kiện

Bao phủ nhánh lệnh

Bao phủ chức năng

Bao phủ FSM

Bao phủ trạng thái

Bao phủ chuyển trạng thái

4.2.3.3 3. Quan sát và kiểm tra tín hiệu đầu ra

Phương pháp 1: Quan sát và so sánh thủ công

Tín hiệu đầu vào/ đầu ra được hiển thị dưới dạng biểu đồ thời gian

In ra tín hiệu đầu ra dưới dạng text

$display, $strobe

$monitor

Dễ có sai sót do người thực hiện

Không tự động hóa được

Thường được thay thế bằng testbench tự kiểm tra (self-test)

Phương pháp 2: Quan sát và kiểm tra kết quả đầu ra tự động

Cần có khối tính toán kết quả đầu ra

Cách 1: Tính toán đầu ra "đúng" bằng mã Verilog trong testbench

Ví dụ:

4.2.3.3..1.1.1.1 `timescale 1ns /100 fs // time_unit/time_precision-định nghĩa đơn vị thời gian mô phỏng

module adder4bit_tb; // Khai báo các tín hiệu nối vào DUT reg[8:0] stim; // inputs to DUT are regs

wire[3:0] S; // outputs of DUT are wires wire C4; // instantiate DUT adder4bit adder4bit_DUT (.sum(S),

.c_out(C4), .a(stim[8:5]), .b(stim[4:1]), .c(stim[0])); // stimulus generation -- tạo tín hiệu đầu vào initial

begin stim = 9'b0000_0000_0; // at 0 ns #10 stim = 9'b1111_0000_1; // at 10 ns #10 stim =

9'b0000_1111_1; // at 20 ns #10 stim = 9'b1111_0001_0; // at 30 ns #10 stim = 9'b0001_1111_0; //

at 40 ns #10 $stop; // at 50 ns - stops simulation end // outputs observation initial $monitor("%t, a =

%d, b=%d, ci=%b, s = %d, co=%b", $time, stim[8:5], stim[4:1],stim[0],s, c4) // outputs self-test always

@(stim, s, c4) begin if ({c4, s} != stim[8:5]+stim[4:1]+stim[0]) $display ("FAIL: %t, a = %d, b=%d,

ci=%b, s = %d, co=%b", $time, stim[8:5], stim[4:1],stim[0],s, c4); end endmodule

Testbench thực hiện việc mô tả chức năng mạch một lần nữa (nguyên lý duplicate

trong kiểm tra)

4.2.3.3..1.1.1.2 Chú ý: mạch được mô tả trong testbench không cần phải tổng hợp => có thể mô tả bằng các

cấu trúc ngôn ngữ bậc cao (trừu tượng hơn) => đơn giản hơn mạch DUT

Cách 2: Tính toán đầu ra "đúng" bằng chương trình phần mềm (C/C++,

Matlab/Simulink)

Giao tiếp thông qua tệp tin

4.2.3.3..1.1.1.3 Phần mềm sẽ ghi mẫu đầu vào và đầu ra "đúng" tương ứng vào file

4.2.3.3..1.1.1.4 Testbench sẽ đọc file để lấy đầu vào và đầu ra "đúng"

Giao tiếp thông qua giao diện PLI, giao diện HIL,...

4.2.3.4 4. Tạo tín hiệu clk

Dùng always

initial clk = 0; always @(clk) clk = #5 ~clk;

Dùng forever

initial begin clk = 0; forever #5 clk = ~clk; end

4.3 4.3. Một số câu lệnh có thể dùng trong testbench

4.3.1 4.3.1. Các lệnh lặp

4.3.1.1 for

Cú pháp

for (starting_statement; condition_expression; ending_statement)

Ví dụ 4.3.1: for

reg [15:0] rf[0:15]; // memory structure for modeling register file reg [5:0] w_addr; // address

to write to for (w_addr=0; w_addr<16; w_addr=w_addr+1) rf[w_addr[3:0]] = 16’h0000; // initialize

register file memory

4.3.1.2 while

Cú pháp

while (condition_expression)

Ví dụ 4.3.2: while

reg [15:0] flag; reg [4:0] index; initial begin index=0; found=1’b0; while ((index<16) &&

(!found)) begin if (flag[index]) found = 1’b1; else index = index + 1; end if (!found)

$display(“non-zero flag bit not found!”); else $display(“non-zero flag bit found in position %d”,index);

end

4.3.1.3 repeat

Cú pháp

repeat (number_of_iteration)

Trong đó: number_of_iteration là 1 hằng số nguyên hoặc 1 biến

Lặp số lần cố định

Số lần lặp có thể là một biến, nhưng chỉ được tính một lần khi bắt đầu vòng lặp

Dùng khi muốn đợi một số xác định chu kỳ đồng hồ

Ví dụ 4.3.3: repeat

initial begin inc_DAC = 1’b1; repeat(4095) @(posedge clk); // bring DAC right up to point of

rollover inc_DAC = 1’b0; inc_smpl = 1’b1; repeat(7)@(posedge clk); // bring sample count up to 7

inc_smpl = 1’b0; end

4.3.1.4 forever

Cú pháp

forever statements;

Ví dụ 4.3.4: forever

initial begin clk = 0; forever #10 clk = ~ clk; end

4.3.2 4.3.2. Khối lệnh và điều khiển khối lệnh

4.3.2.1 Khối lệnh tuần tự - begin/end

bao khối lệnh thực hiện tuần tự

4.3.2.2 Khối lệnh song song - fork/join

bao khối lệnh thực hiện song song

các câu lệnh trong khối được thực hiện đồng thời

Thời gian trễ trong các câu lệnh nằm giữa fork/join được tính tương đối kể từ khi khối lệnh

được bắt đầu thực hiện

Thích hợp để chờ 2 sự kiện xuất hiện nhưng không biết sự kiện nào xuất hiện trước

begin fork @Aevent @Bevent join areg = breg; end

Chú ý: fork/join có thể gây ra đua tín hiệu (hazard)

Khi nhiều khối fork/join cùng gán giá trị cho một biến

4.3.2.3 Đặt tên khối lệnh

Có thể định nghĩa biến địa phương bên trong khối lệnh đã được đặt tên

Các biến địa phương có thể được truy cập bằng cách truy cập phân cấp

Có thể dừng (disable) một khối lệnh có tên

Hình vẽ

4.3.2.4 Tạm dừng thực hiện một khối lệnh

Cú pháp: disable block_name;

Tạm dừng thực hiện một khối lệnh

Ví dụ 4.3.5: disable

`timescale 1ns/1ns module test_diable(); integer a, b; integer i; reg clk; initial begin :

break for (i = 0; i < 20; i = i+1) begin : continue @(posedge clk) if (a == 0) //

"continue" loop disable continue; // Dừng không thực hiện lệnh bên trong khối continue

if (a == b) // "break" from loop disable break; // Dừng không thực hiện lệnh bên trong

khối break $display("%t:Inside continue block a=%d,b=%d,i=%d",$time,a,b,i); end

$display("%t:Inside break block a=%d,b=%d,i=%d",$time,a,b,i); end initial begin a = 2; b = 1;

#20 a = 0; #20 a = 3; #20 a = 1; end initial begin clk = 0; forever #5 clk = ~clk; end // initial

$monitor ("%t:a=%d,b=%d,i=%d",$time,a,b,i); endmodule;

Kết quả mô phỏng

run 100ns # 5:Inside continue block a= 2,b= 1,i= 0 #

15:Inside continue block a= 2,b= 1,i= 1 # 45:Inside continue block a=

3,b= 1,i= 4 # 55:Inside continue block a= 3,b= 1,i= 5

4.3.3 4.3.3 Vào ra file

4.3.3.1 Thực hiện kiểm chứng tự động

4.3.3.2 Đầu vào, đầu ra được đưa vào file và độc lập với testbench

Đầu vào và đầu ra chuẩn có thể được tạo ra bởi phần mềm ở ngôn ngữ bậc cao như C/C++,

Matlab/Simulink

Dùng file để kết nối 2 mức mô tả hệ thống

Mức phần mềm: mô tả thuật toán

Mức phần cứng (DUT): mô tả triển khai RTL/behavior

4.3.3.3 Các hàm thao tác trên file

Đóng mở

$fopen mở file, trả về 1 handle để sử dụng trong các lệnh khác

integer fd = $fopen(“filename”); integer fd = $fopen(“filename”, r);

Nếu không mở được file trả về 0

$fclose đóng file

$fclose(fd)

Ghi

$fdisplay, $fwrite ghi dữ liệu vào file khi được gọi. $fdisplay thêm 1 ký tự bắt đầu dòng mới

vào dữ liệu. $write không thêm.

$fstrobe ghi vào file, nhưng đợi đến khi tất cả các lệnh khác trong cùng thời gian mô phỏng

kết thúc trước khi ghi.

initial #1 a=1; b=0; $fstrobe(hand1, a,b); b=1;

Đoạn mã trên sẽ ghi giá trị 1 1 vào file cho a và b

$fmonitor ghi vào file bất cứ khi nào các tham số truyền cho nó thay đổi

$fdisplay(fd, “out=%b in=%b”, out, in);

Đọc

Đọc một ký tự

$fgetc

Ví dụ 3.3.6: fgetc

4.3.3.3..1.1.1.1 module file_read() parameter EOF = -1; integer file_handle,error,indx; reg signed [15:0]

wide_char; reg [7:0] mem[0:255]; reg [639:0] err_str; initial begin indx=0; file_handle =

$fopen(“text.txt”,”r”); error = $ferror(file_handle,err_str); if (error==0) begin wide_char = 16’h0000;

while (wide_char!=EOF) begin wide_char = $fgetc(file_handle); mem[indx] = wide_char[7:0];

$write(“%c”,mem[indx]); indx = indx + 1; end end else $display(“Can’t open file…”);

$fclose(file_handle); end endmodule

Đọc một dòng

$fgets

Ví dụ 3.3.7: fgets

4.3.3.3..1.1.1.2 module file_read2() integer file_handle,error,indx,num_bytes_in_line; reg [256*8:1]

mem[0:255],line_buffer; reg [639:0] err_str; initial begin indx=0; file_handle = $fopen(“text2.txt”,”r”);

error = $ferror(file_handle,err_str); if (error==0) begin num_bytes_in_line =

$fgets(line_buffer,file_handle); while (num_bytes_in_line>0) begin mem[indx] = line_buffer;

$write(“%s”,mem[indx]); indx = indx + 1; num_bytes_in_line = $fgets(line_buffer,file_handle); end

end else $display(“Could not open file text2.txt”);

Đọc theo biến

$fscanf

Ví dụ 3.3.8: fscanf

4.3.3.3..1.1.1.3 module file_read3() integer file_handle,error,indx,num_matches; reg [15:0] mem[0:255][1:0];

reg [639:0] err_str; initial begin indx=0; file_handle = $fopen(“text3.txt”,”r”); error =

$ferror(file_handle,err_str); if (error==0) begin num_matches = $fscanf(file_handle,”%h

%h”,mem[indx][0],mem[indx][1]); while (num_matches>0) begin $display(“data is: %h

%h”,mem[indx][0],mem[indx[1]); indx = indx + 1; num_matches = $fscanf(file_handle,”%h

%h”,mem[indx][0],mem[indx][1]); end end else $display(“Could not open file text3.txt”);

Đọc file theo khối bộ nhớ

$readmemb(“<file_name>”,<memory>);

$readmemb(“<file_name>”,<memory>,<start_addr>,<finish_addr>);

$readmemh(“<file_name>”,<memory>);

$readmemh(“<file_name>”,<memory>,<start_addr>,<finish_addr>);

Ví dụ cấu trúc file

Ví dụ 3.3.9: Đọc bộ nhớ

module rom(input clk; input [7:0] addr; output [15:0] dout); reg [15:0] mem[0:255];

// 16-bit wide 256 entry ROM reg [15:0] dout; initial $readmemh(“constants”,mem);

always @(negedge clk) begin

/////////////////////////////////////////////////////////// // ROM presents data

on clock low // ///////////////////////////////////////////////////////// dout <=

mem[addr]; end endmodule

Ví dụ 3.3.10: Testbench sử dụng file

module CLA16_selft_tb(); reg [32:0] stim; reg [55:0] inout_patterns [0:10]; wire [15:0] s; wire

co; reg [4:0] addr; CLA16 cla16_dut(.a(stim[15:0]), .b(stim[31:16]), .ci(stim[32]), .s(s), .co(co));

initial $monitor("%t: a=%h, b=%h, ci=%b, s=%h, co=%b, correct_s=%h, correct_co=%b", $time,

stim[15:0], stim[31:16], stim[32], s, co, inout_patterns[addr][51:36],inout_patterns[addr][52]); //

read input-output patterns from file and // drive to input // in file correct-outputs.txt the data is

arranged as follow: // each input patterns and corresponding correct output values are given as a

hexa number where // first four digits is a value [15:0] // next four is b value [31:16] // next one

digit is ci value [35:32] // next four digits is s value [51:36] // next one digit is co value [55:52] //

total are 14 digits initial begin: input_gen $readmemh("correct-outputs.txt", inout_patterns);

stim = 32'h0; for (addr = 0;addr < 11; addr=addr+1) begin stim = inout_patterns[addr][32:0];

#5; end end // output self-test always @(stim) begin: output_selftest if

((co!==inout_patterns[addr][52])|(s!==inout_patterns[addr][51:36])) $display ("WRONG!!!-%t:

a=%h, b=%h, ci=%b, s=%h, co=%b, correct_s=%h, correct_co=%b", $time, stim[15:0],

stim[31:16], stim[32], s, co,inout_patterns[addr][51:36],inout_patterns[addr][52]); end endmodule

4.3.4 4.3.4 Đặt giá trị tín hiệu trong mạch

4.3.4.1 Đưa mạch đến một trạng thái xác định và bắt đầu mô phỏng từ đó

4.3.4.2 Chỉ sử dụng trong testbench, không có trong thực tế

4.3.4.3 Giúp đi đến gần trạng thái có thể xảy ra lỗi của mạch

4.3.4.4 Dùng kiểm tra mạch dãy "sâu" (cần nhiều chu kỳ để đến được một trạng thái bất kỳ

của mạch)

Đưa mạch đến một trạng thái

Kiểm tra các bước chuyển trạng thái từ trạng thái đó

Kiểm tra đầu ra tương ứng

4.3.4.5 force signal_name = value; release signal_name = value;

Chú ý: có thể dùng cách truy cập phân cấp (dấu chấm) để chỉ tới tín hiệu sâu bên trong các

module con

4.3.4.6 Ví dụ 4.3.6: force/release

Testbench

module gray_counter_tsb(); reg clk, rst_n; wire [3:0] out; gray_counter GC(.cnt(out),

.clk(clk), .rst_n(rst_n)); // DUT initial $monitor("%t out: %b rst_n: %b state: %b", $time, out, rst_n,

GC.state); // no clock initial begin clk = 0; forever #5 clk = ~clk; // What is the clock period? end

initial begin rst_n = 1; #10 rst_n = 0; #90 rst_n = 1; force GC.state = 4'b0001; #10 release GC.state;

#10 force GC.state = 4'b0010; #10 release GC.state; #10 force GC.state = 4'b0011; #10 release

GC.state; #10 force GC.state = 4'b0100; #10 release GC.state; #10 force GC.state = 4'b0101; #10

release GC.state; #10 force GC.state = 4'b0110; #10 release GC.state; #10 force GC.state = 4'b0111;

#10 release GC.state; #10 force GC.state = 4'b1000; #10 release GC.state; #10 force GC.state =

4'b1001; #10 release GC.state; #10 force GC.state = 4'b1010; #10 release GC.state; #10 force

GC.state = 4'b1011; #10 release GC.state; #10 force GC.state = 4'b1100; #10 release GC.state; #10

force GC.state = 4'b1101; #10 release GC.state; #10 force GC.state = 4'b1110; #10 release GC.state;

#10 force GC.state = 4'b1111; #10 release GC.state; end // initial endmodule

gray_counter

module gray_counter (input clk, rst_n, output [3:0] cnt); reg [3:0] state; always @(posedge

clk) begin if (~rst_n) state <= 4'b0000; else state <= state+1; end assign cnt = state ^

{1'b0,state[3:1]}; endmodule

4.4 4.4. Một số hàm hệ thống trong Verilog

4.4.1 $stop

4.4.1.1 Dừng mô phỏng vào chế độ giao tiếp lệnh với người dùng, cho phép theo dõi các tín

hiệu và gỡ lỗi

4.4.2 $finish

4.4.2.1 Kết thúc chương trình mô phỏng quay về hệ điều hành

4.4.3 $reset

4.4.3.1 đặt lại thời gian mô phỏng về 0

4.4.4 $time, $stime, $realtime

4.4.4.1 Trả về thời gian mô phỏng hiện tại dạng 64 bit nguyên, 32 bit nguyên, số thực

4.4.5 $display, $strobe, $monitor

4.4.5.1 Cú pháp

$display ("format_string", par_1, par_2, ... ); $strobe ("format_string", par_1, par_2, ... );

$monitor ("format_string", par_1, par_2, ... ); $displayb (as above but defaults to binary..); $strobeh

(as above but defaults to hex..); $monitoro (as above but defaults to octal..);

format string tương tự printf của C

4.4.5.2 $display và $strobe được thực hiện 1 lần khi được gọi

4.4.5.3 $monitor được thực hiện bất cứ khi nào các tham số truyền vào thay đổi

4.4.5.4 Được sử dụng trong testbench khi mô phỏng mạch

4.4.5.5 $display(“At time %t count = %h”,$time,cnt);

4.4.6 $random

4.4.6.1 Tạo một số nguyên ngẫu nhiên khi được gọi

4.4.6.2 Ở lần gọi đầu tiên có thể truyền cho hàm một số seed (các lần gọi với cùng một số

seed sẽ tạo ra cũng một chuỗi ngẫu nhiên

4.4.6.3 Nếu không truyền số seed, số seed sẽ được lấy từ đồng hồ hệ thống

4.4.7 $dumpfile, $dumpvar, $dumpon, $dumpoff, $dumpall

4.4.7.1 $dumpfile("filename.vcd")

Đặt file chứa các giá trị biến được in ra

4.4.7.2 $dumpvar

In ra giá trị tất cả các biến trong thiết kế

4.4.7.3 $dumpvar(n, top)

In ra giá trị các biến trong module top và n-1 module con phía dưới

4.4.7.4 Subtopic

4.4.7.5 $dumpon

Bắt đầu thực hiện in

4.4.7.6 $dumpoff

Kết thúc việc in ra các biến

4.4.8 Chú ý: Các hàm này không dùng mô tả mạch mà chủ yếu dùng để gỡ lỗi mạch khi mô

phỏng, trong testbench

5 Chương 5. Tổng hợp. Tham khảo: http://asic-soc.blogspot.de

5.1 5.1. Giới thiệu chung

5.1.1 Quy trình thiết kế vi mạch

5.1.1.1

5.1.1.2 Thiết kế vật lý là quá trình đặt các layout các cổng lên phiến đế (Place) và kết nối

các cổng bằng các đường dây kim loại (Route)

5.1.2 Định nghĩa

5.1.2.1 Tổng hợp là quá trình chuyển từ mô tả RTL/behavior thành mạch ở lớp cổng

RTL/Behavior ở ngôn ngữ HDL (Verilog/VHDL) mô tả hoạt động của mạch bằng

RTL: mô tả quá trình xử lý dữ liệu của mạch (Dataflow)

Behavior: Mô tả các bước hoạt động của mạch-FSMD

Mạch ở lớp cổng: Các cổng logic kết nối với nhau

Mạch lớp cổng generic không phụ thuộc công nghệ chế tạo khi các cổng không đi kèm thông

tin về layout, kích thước transitor, bố trí transitor, điểm kết nối

Không dùng được để chế tạo vi mạch

Mạch lớp cổng phụ thuộc công nghệ chế tạo, nếu các cổng có thông tin về layout, kích thước

transitor, điểm kết nối

Cho phép xác định chính xác thời gian hoạt động/độ trễ/tốc độ của mạch

5.1.2.2 Hai bước tổng hợp

Dịch

Chuyển đổi mô tả Verilog thành mô tả lớp cổng generic

Tối ưu và ánh xạ cổng

Ánh xạ các cổng generic thành các cổng trong thư viện cell chuẩn phụ thuộc công nghệ.

Tối ưu mạch để đạt được các điều kiện kỹ thuật đặt ra

Hình vẽ

5.1.3 Nhiệm vụ của tổng hợp

5.1.3.1 Mức ưu tiên cao nhất: Đảm bảo chức năng của mạch

Mạch netlist tổng hợp được tương đương mạch mô tả ở Verilog

Tương đương về hàm logic Bool

Tương đương về sự thứ tự tuần tự trong mạch dãy

Không tạo ra các latch không mong muốn

5.1.3.2 Mức ưu tiêu 2: Thỏa mãn các giới hạn về luật thiết kế

Được cho trong thư viện công nghệ bởi các nhà sản xuất ASIC

Người thiết kế không thể thay đổi các giới hạn luật thiết kế

Người thiết kế có thể áp đặt giới hạn khắt khe hơn, nhưng không thể áp đặt giới hạn nhẹ

hơn

Ví dụ: Giới hạn về tốc độ chuyển giá trị tín hiệu, số fanout tối đa,...

5.1.3.3 Mức ưu tiên 3: Thỏa mãn các giới hạn tối ưu

Được đặt ra bởi người thiết kế, theo thứ tự ưu tiên như sau

1. Thời gian (Speed/Timing)

2. Kích thước (Area)

3. Năng lượng (Power)

Giới hạn này phải thực tế, nhưng không được quá nhẹ

Nếu không sẽ được thiết kế tồi

5.1.4 Đầu vào/ra của tổng hợp

5.1.4.1 Đầu vào

Mã HDL (.v, vhd)

Giới hạn về luật thiết kế

Giới hạn tối ưu

Tốc độ

Kích thước

Năng lượng

5.1.4.2 Đầu ra

Mô tả mạch ở mức cổng phụ thuộc công nghệ

5.2 5.2. Chuẩn bị tổng hợp

5.2.1 5.2.1 Thư viện đích

5.2.1.1 Cho biết công nghệ được sử dụng để sản xuất mạch

Cần thư viện các cổng logic phụ thuộc công nghệ

Thư viện target được dùng để tạo ra mạch cổng phụ thuộc công nghệ

Thư viện target được cung cấp bởi nhà sản xuất IC hoặc nhóm thiết kế standard cell .lib

Các thư viện standard cell là được lưu trong file .db ở trong các thư mục libs../../LM

5.2.1.2 Thư viện standard cells ở mức logic. Chứa các thông tin về các cổng logic cơ bản

Tên cell

Kích thước cell

Đầu vào/ra

Hàm logic

Tham số thời gian

5.2.1.3 Lệnh DC: set_app_var target_library

dc_shell-topo> set_app_var target_library libs/mw_lib/sc/LM/sc_max.db

libs/mw_lib/sc/LM/sc_max.db

5.2.1.4 Bắt buộc phải đặt target_library

5.2.2 5.2.2 Thư viện liên kết

5.2.2.1 Khi tổng hợp cần biết mô tả cấu trúc tất cả các module sử dụng trong mạch

Được chứa trong thư viện link

Ví dụ: Module DDR-RAM, module CPU được mua của hãng thứ 3

5.2.2.2 Nếu không có sẽ báo lỗi

Unable to resolve reference "..."

5.2.2.3 Lệnh DC set_app_var link_library

dc_shell-topo> set_app_var link_library * libs/mw_lib/sc/LM/sc_max.db

5.2.2.4 Thường link_library sẽ gồm * và target_library

* chỉ đến bộ nhớ, là phần dc lưu trữ tạm thời các thư viện nó đã tổng hợp hoặc đã nạp

Ví dụ: một file .v chứa module con

Các file ddc chứa module con đã được tổng hợp

Có thể dùng target_library để làm thư viện link nếu file .v bản đầu là RTL/behavior không

phụ thuộc công nghệ

Nếu file .v ban đầu là file đã tổng hợp phụ thuộc công nghệ thì link library phải là library

công nghệ cũ

5.2.3 5.2.3 Thư viện vật lý

5.2.3.1 Thư viện vật lý chứa các thông số giúp dc tính toán chính xác thời gian trễ của mạch

hơn trong chế độ hoạt động topological (tùy chọn -topo khi chạy dc_shell)

5.2.3.2 Gồm

Reference library

Standard Cells

Các cổng logic căn bản ở lớp transistor/layout

IP hoặc Macro cells

Ví dụ: RAM module, Multiplier IP

I/O Pad cells

Chứa thông tin ở các lớp/mức khác nhau

CEL

Thông tin đầy đủ về layout cell - đủ để chế tạo

FRAM

Thông tin về kích thước cell và vị trí các chân trong cell

DC cần dùng

LM

Thông tin về hàm logic và timing của cell

DC cần dùng

Chính là thư viện target

DC dùng định dạng Milkyway cho reference library

Được cung cấp bởi nhà chế tạo IC

Có thể được tạo ra từ file LEF, GDS bằng cách dùng tool Synopsys Milkyway

Tham khảo

Data preparation user guide

Dữ liệu công nghệ

Technology File

Định nghĩa về các lớp đi dây, các lỗ nối giữa các lớp, luật DRC

TLUPLUS file

Chứa các tham số về tụ điện và điện trở ký sinh

Layer Mapping file

Chứa các tên khác nhau cho cùng một lớp

5.2.3.3 Để tạo cần

Trỏ tới reference library

Nạp file technology

Nạp file tluplus

5.2.3.4 Lệnh

set_app_var mw_referecen_library

set_app_var mw_design_library

create_mw_lib

Chỉ cần tạo một lần

open_mw_lib

Sau đó chỉ cần mở

check_library

set_tluplus_files

check_tluplus_files

dc_shell-topo> set_app_var mw_reference_library libs/mw_lib/sc libs/mw_lib/sc dc_shell-

topo> set_app_var mw_design_library mylib mylib dc_shell-topo> create_mw_lib -technology

libs/tech/cb13_6m.tf -mw_reference_library $mw_reference_library $mw_design_library Start to

load technology file libs/tech/cb13_6m.tf. Technology file libs/tech/cb13_6m.tf has been loaded

successfully.

5.2.4 5.2.4 Quản lý các tệp

5.2.4.1 Tạo cấu trúc thư mục

Thư mục chính chứa toàn bộ dữ liệu về thiết kế: risc_design.

Là thư mục mà tại đó ta gọi dc_shell -topo

Thư mục con và files

mapped

Chứa các file .ddc mô tả mạch gồm các cổng phụ thuộc công nghệ (sau khi đã ánh xạ

từ cổng không phụ thuộc công nghệ) vào thư viện cổng theo công nghệ

libs

Chứa các file .db các thư viện khối, IPs được sử dụng trong thiết kế

cons

Chứa các file .cons là các câu lệnh tcl của dc_shell để thiết lập giới hạn thời gian, diện

tích năng lượng của mạch

rtl

Chứa các file thiết kế ở ngôn ngữ HDL

unmapped

Chứa các file .ddc mô tả mạch cổng không phụ thuộc công nghệ

.synopsys_dc.setup

File gồm các lệnh tcl sẽ được thực thi khi gọi dc_shell

Lệnh sử dụng: mkdir

minh@dolcetto-suse:/home/projects> mkdir dc-ex minh@dolcetto-suse:/home/projects>

mkdir dc-ex/rtl minh@dolcetto-suse:/home/projects> mkdir dc-ex/work minh@dolcetto-

suse:/home/projects> mkdir dc-ex/libs minh@dolcetto-suse:/home/projects> mkdir dc-ex/cons

minh@dolcetto-suse:/home/projects> mkdir dc-ex/mapped minh@dolcetto-suse:/home/projects>

mkdir dc-ex/unmapped minh@dolcetto-suse:/home/projects> ll dc-ex total 24 drwx--x--x 2 minh users

4096 2012-04-18 08:20 cons drwx--x--x 2 minh users 4096 2012-04-18 08:20 libs drwx--x--x 2 minh

users 4096 2012-04-18 08:20 mapped drwx--x--x 2 minh users 4096 2012-04-18 08:20 rtl drwx--x--x 2

minh users 4096 2012-04-18 08:20 unmapped drwx--x--x 2 minh users 4096 2012-04-18 08:20 work

Chạy dc_shell với option -topo

Chú ý: vào thư mục làm việc dc-ex

minh@dolcetto-suse:/home/projects> cd dc-ex minh@dolcetto-suse:/home/projects/dc-ex>

dc_shell -topo DC Professional (TM) DC Expert (TM) DC Ultra

(TM) FloorPlan Manager (TM) HDL Compiler (TM) VHDL

Compiler (TM) Library Compiler (TM) DesignWare Developer (TM)

DFT Compiler (TM) BSD Compiler Power Compiler (TM) Version D-

2010.03-SP5-2 for linux -- Jan 21, 2011 Copyright (c) 1988-2010 by Synopsys, Inc.

ALL RIGHTS RESERVED This software and the associated documentation are confidential and

proprietary to Synopsys, Inc. Your use or disclosure of this software is subject to the terms and

conditions of a written license agreement between you, or your company, and Synopsys, Inc. The above

trademark notice does not imply that you are licensed to use all of the listed products. You are licensed

to use only those products for which you have lawfully obtained a valid license key. Initializing...

Starting shell in Topographical mode... dc_shell-topo>

5.2.4.2 set_app_var search_path "$search_path rtl unmapped mapped"

Thêm các đường dẫn để dc tìm các file .v, .db, .ddc

5.2.4.3 define_design_lib WORK -path ./work

Các file tạm sinh ra trong quá trình tổng hợp được lưu trong work

Giữ thư mục chính dc-ex gọn gàng, trật tự

5.2.5 5.2.5 Tổng kết

5.2.5.1 các thiết lập đường dẫn cho thư viện có thể được viết vào file .tcl và được gọi ra

bằng file .synopsys_dc.setup

5.2.5.2 chỉ cần sửa các biến đường dẫn trong file common_setup.tcl cho các thiết kế khác

nhau

5.2.5.3 common_setup.tcl

đặt tên cho các biến đường dẫn

sử dụng lênh : set tên_biến đường dẫn

Ví dụ

##########################################################################################

# User-defined variables for logical library setup in dc_setup.tcl

##########################################################################################

set ADDITIONAL_SEARCH_PATH "../ref/libs/mw_lib/sc/LM ./rtl ./scripts" ;# Directories containing logical

libraries,

# logical design and script files.

set TARGET_LIBRARY_FILES sc_max.db ;# Logical technology library file

set SYMBOL_LIBRARY_FILES sc.sdb ;# Symbol library file

##########################################################################################

# User-defined variables for physical library setup in dc_setup.tcl

##########################################################################################

set MW_DESIGN_LIB TOP_LIB ;# User-defined Milkyway design library name

set MW_REFERENCE_LIB_DIRS ../ref/libs/mw_lib/sc ;# Milkyway reference libraries

set TECH_FILE ../ref/libs/tech/cb13_6m.tf ;# Milkyway technology file

set TLUPLUS_MAX_FILE ../ref/libs/tlup/cb13_6m_max.tluplus ;# Max TLUPlus file

set MAP_FILE ../ref/libs/tlup/cb13_6m.map ;# Mapping file for TLUplus

5.2.5.4 dc_setup.tcl

sử dụng các biến trong file common_setup/tcl để chỉ tới các thư viện link,target ...

ví dụ

######################################################################

# Logical Library Settings

######################################################################

set_app_var search_path "$search_path $ADDITIONAL_SEARCH_PATH"

set_app_var target_library $TARGET_LIBRARY_FILES

set_app_var link_library "* $target_library"

set_app_var symbol_library $SYMBOL_LIBRARY_FILES

######################################################################

# Physical Library Settings

######################################################################

set_app_var mw_reference_library $MW_REFERENCE_LIB_DIRS

set_app_var mw_design_library $MW_DESIGN_LIB

create_mw_lib -technology $TECH_FILE \

-mw_reference_library $mw_reference_library \

$mw_design_library

open_mw_lib $mw_design_library

set_tlu_plus_files -max_tluplus $TLUPLUS_MAX_FILE \

-tech2itf_map $MAP_FILE

5.2.5.5 .synopsys_dc.setup

dùng để gọi 2 file dc_setup và common_setup

tự động chạy khi gọi dc_shell tại đường dẫn chứa file này

ví dụ:

source common_setup.tcl

source dc_setup.tcl

ngoài ra có thế viết thêm các lệnh check lib để kiểm tra thư viện

5.3 5.3. Các điều kiện giới hạn tổng hợp

5.3.1 5.3.1. Giới hạn thời gian

5.3.1.1 Định nghĩa

Là thông tin thời điểm xuất hiện về tín hiệu đồng hồ, đầu vào, đầu ra của mạch. Thông tin

này cho phép bộ tổng hợp kiểm tra điều kiện setup và hold của các FF trong mạch

Thông tin đồng hồ: xác định thời điểm xuất hiện sườn đồng hồ điều khiển FF

Cho phép xác định/và tối ưu độ trễ của các đường tín hiệu từ đầu ra Q của FF đến đầu

vào D của FF (Đường tín hiệu REG-REG)

Thông tin đầu vào: xác định thời điểm đến của tín hiệu đầu vào so với sườn đồng hồ

Cho phép xác định/và tối ưu độ trễ của các đường tín hiệu từ đầu vào PI đến đầu vào

D của FF (Đường tín hiệu PI-REG)

Thông tin đầu ra: xác định thời điểm cần đưa tín hiệu đầu ra so với sườn đồng hồ

Cho phép xác định/và tối ưu độ trễ của các đường tín hiệu từ đầu ra Q của FF đến đầu

ra PO (Đường tín hiệu REG-PO)

Hình vẽ

5.3.1.2 Thông tin đồng hồ

Đặt giới hạn thời gian trễ tối đa cho đường logic tổ hợp giữa 2 FF: FF_start và FF_stop

Tmax(REG-REG)=min(t_clk_cap-t_clk_launch)-t_setup

Khoảng cách giữa 2 sườn xung đồng hồ liên tiếp dùng để điều khiển 2 FF_start, FF_stop

trong đường tín hiệu đang xét.

Hai loại sườn đồng hồ

Điều khiển 2 FF_start, FF_stop được dùng như mốc tham chiếu để tính toán thời gian

(thời điểm)

Sườn bắt dữ liệu (capture edge)

Là sườn được dùng để phát hiện và lưu trữ dữ liệu vào FF_stop

Xuất hiện tại thời điểm t_clk_cap

Sườn xuất dữ liệu (launch edge)

Là sườn được dùng để đưa dữ liệu ra khỏi FF_start

Xuất hiện tại thời điểm t_clk_lauch

Hình vẽ

Chú ý: loại sườn đồng hồ được xác định ứng với từng đường tín hiệu trong mạch

Thời điểm xuất hiện 2 sườn đồng hồ bắt dữ liệu và xuất dữ liệu được quyết định bởi các

khoảng thời gian

Chu kỳ và độ rộng xung đồng hồ

Hình vẽ

5.3.1.2..1.1.1.1

Lệnh tạo đồng hồ

5.3.1.2..1.1.1.2 create_clock -period chu_kỳ_clk [get_ports tên_clk]

5.3.1.2..1.1.1.3 create_clock -period 3.0 [get_ports clk]

# A 333Mhz clock is a 3.0ns period:

Lệnh đặt độ rộng xung đồng hồ

5.3.1.2..1.1.1.4 set_min_pulse_width -high 2.5 [all_clocks]

5.3.1.2..1.1.1.5 set_min_pulse_width -low 2.0 [all_clocks]

Độ trễ do đường tín hiệu đồng hồ (Clock latency)

Lệnh đặt latency

5.3.1.2..1.1.1.6 set_clock_latency -source

5.3.1.2..1.1.1.7 Độ trễ của các đường clk ngoài module đang xét

5.3.1.2..1.1.1.8 Có thể coi là độ trễ của đầu vào clk

5.3.1.2..1.1.1.9 set_clock_latency -max

5.3.1.2..1.1.1.10 Độ trễ đường clk bên trong module

5.3.1.2..1.1.1.11 sau khi post-layout thì dùng lệnh

5.3.1.2..1.1.1.12 set_propagated_clock

5.3.1.2..1.1.1.13 set_clock_latency -source -max 0.7 [get_clocks clk] set_clock_latency -max 0.3

[get_clocks clk]

Thời gian chuyển giá trị (0->1, 1->0)/Độ dốc sườn xung đồng hồ

Lệnh đặt transition

5.3.1.2..1.1.1.14 set_clock_transition

5.3.1.2..1.1.1.15 set_clock_transition 0.12 [get_clocks clk]

# The maximum clock transition is 120ps or 0.12ns

Sự thay đổi thời gian đến của các sườn đồng hồ (clock uncertainty)

Độ chênh thời gian lan truyền đồng hồ tới FF_start, FF_stop (Clock skew)

5.3.1.2..1.1.1.16 Độ chênh dương

5.3.1.2..1.1.1.17 Khi sườn bắt đến sau sườn xuất

5.3.1.2..1.1.1.18 Đồng hồ và dữ liệu đi theo cùng hướng

5.3.1.2..1.1.1.19 Độ chênh dương làm vi phạm điều kiện hold

5.3.1.2..1.1.1.20 Độ chênh dương hỗ trợ điều kiện setup

5.3.1.2..1.1.1.21 Độ chênh âm

5.3.1.2..1.1.1.22 Hình vẽ

5.3.1.2..1.1.1.23

Độ chênh xê dịch sườn xung đồng hồ (clock jitter) do nguồn tạo đồng hồ

Phần dự trữ (margin)

Lệnh đặt skew, jitter, margin

5.3.1.2..1.1.1.24 set_clock_uncertainty -setup 0.15 [get_clocks clk]

# The +/-30ps internal clock delay variation to register clock pins results in a 60ps worst case skew or

uncertainty, if you launch

# late (+30ps) and capture early (-30ps)r; Add 40ps due to jitter and 50ps for setup margin;

# This equals 150ps or 0.15 ns of total uncertainty.

Hình vẽ

Lệnh DC

Khoảng cách giữa 2 sườn bắt và xuất dữ liệu được tín bằng khoảng thời gian ngắn nhất giữa

thời điểm xuất hiện sườn bắt và xuất dữ liệu

=min(t_clk_cap-t_clk_launch)

Nếu 2 FF đều được điều khiển bằng sườn lên (xuống)

t_clk_launch_min = network_latency+source_latency-0.5*uncertainty

t_clk_launch_max = network_latency+source_latency+0.5*uncertainty

t_clk_capture_min = clk_period+network_latency+source_latency-0.5*uncertainty

t_clk_launch_max = clk_period+network_latency+source_latency+0.5*uncertainty

Đối với các thiết kế không dùng clk thì vẫn phải constraint như trên với 1 tín hiệu virtual_clk

5.3.1.3 Thông tin đầu vào/độ trễ đầu vào(input delay)

Là thời gian xuất hiện muộn nhất của tín hiệu tại đầu vào kể từ khi có sườn xuất tương ứng

với nó

Hình vẽ

Ví dụ 5.3.1

Nếu clock có chu kỳ là 2ns và uncertainty là 0.3ns, thời gian trễ tối đa của phần mạch logic tổ

hợp N là?

Tmax=Tclk-Tsetup-Tinput_delay-Tuncertainty=2-0.2-0.6-0.3=0.9ns

Ví dụ 5.3.2

Hình vẽ

Input delay cần đặt bằng bao nhiêu?

Tinput_delay=2.5-1.5-0.1-0.3=0.6ns

Input delay được phần mềm tổng hợp sử dụng để tính toán/tối ưu độ trễ của đường tín hiệu

(PI-REG)

Tmax(PI-REG)=min(t_clk_cap-t_clk_launch)-t_input_delay-t_setup

5.3.1.4 Thông tin đầu ra/độ trễ đầu ra(output delay)

Là thời gian xuất hiện muộn nhất của tín hiệu tại đầu ra trước khi có sườn bắt tương ứng

của nó

Hình vẽ

Ví dụ 5.3.3

Cho chu kỳ đồng hồ là 2ns, uncertainty là 0.3ns, thời gian trễ tối đa của phần tổ hợp S là bao

nhiêu?

Tmax=Tclk-Toutput_delay-Tuncertainty=2-(0.7+0.1)-0.3=0.9ns

Ví dụ 5.3.4

Xác định output delay cho đầu ra B?

Toutput_delay=Tclk-Tmax=2-0.7=1.3

Output delay được phần mềm tổng hợp sử dụng để tính toán/tối ưu độ trễ đường tín hiệu

(REG-PO)

Tmax(REG-PO)=min(Tclk_cap-Tclk_launch)-Toutput_delay

5.3.1.5 Chú ý 1: Để xác định input, output delay cần xác định rõ thời điểm của sườn xuất và

sườn bắt dữ liệu

5.3.1.6 Chú ý 2: Để giảm bớt thông tin đầu vào/đầu ra dùng output bằng FF

input delay = max FF delay

output delay = clock period - min FF delay

5.3.1.7 Chú ý 3: Giới hạn đường tín hiệu tổ hợp

Cho chu kỳ đồng hồ là 2ns, uncertainty là 0.3

Xác định input delay, output delay cho B và D

Tinput_delay(B)=Tmax(E)=0.4ns

Toutput_delay(D)=Tsetup+Tmax(G) =0.1+0.2=0.3

Xác định độ trễ tối đa của F

Tmax(F)=Tclk-Tinput_delay(B)-Toutput_delay(D)-Tuncertainty =2-0.4-0.3-0.3=1

5.3.1.8 Chú ý 4: Nếu mạch thiết kế là hoàn toàn logic tổ hợp

Để giới hạn thời gian cần tạo ra một đồng hồ ảo

Không gắn với tên một tín hiệu cụ thể trong mạch

Ví dụ

Hình vẽ

5.3.1.9 Lệnh của Design Compiler

5.3.2 5.3.2. Giới hạn luật thiết kế

5.3.2.1 Các tham số tính toán thời gian(Environmental attributes)

Các thông số ảnh hưởng tới độ trễ của cell

Thời gian chuyển giá trị của đầu vào Tinput_r, Tinput_f

Trở kháng kênh dẫn transitor của cổng (R)

Dung kháng tải Cload (đầu ra)

Độ biến thiên quy trình chế tạo: P

Điện áp cung cấp: V

Nhiệt độ hoạt động: T

Giới hạn thời gian chỉ xác định điều kiện cho độ trễ mà không xác định các điều kiện để tính

độ trễ

Chú ý: chỉ cần cung cấp các thông tin cho cổng ở biên của chip (các cổng nối với đầu vào, đầu

ra

5.3.2.2 Hình vẽ minh họa

5.3.2.3 a) Thời gian chuyển giá trị đầu vào/giá trị điện trở cổng đầu kích thích đầu vào

Thời gian chuyển giá trị tại đầu vào sẽ ảnh hưởng tới độ trễ của cổng tại đầu vào

Thời gian chuyển giá trị đầu vào lớn nhất là giới hạn luật thiết kế được quy định trong thư

viện đích (thư viện cell chuẩn)

cell (<cellname>) { cell_leakage_power : 3.748077e-03; threshold_voltage_group : "si38p" ;

area : "8.775" ; …. abc_cell () { … pin (Z) { direction : "output"; } pin (CP) {

direction : "input"; } pin (D) { direction : "input"; } …. } pin (CP) { clock : true;

direction : "input"; related_bias_pin : "VDDB VSSB"; rise_capacitance : 0.001733;

rise_capacitance_range(0.001268,0.002017); capacitance : 0.001706; fall_capacitance :

0.001680; fall_capacitance_range(0.001293,0.001938); max_transition : 0.550; ….. } pin (D)

{ direction : "input"; related_bias_pin : "VDDB VSSB"; rise_capacitance : 0.000752;

rise_capacitance_range(0.000648,0.000960); capacitance : 0.000741; fall_capacitance :

0.000730; fall_capacitance_range(0.000638,0.000875); max_transition : 0.800;

related_power_pin : "VDD"; related_ground_pin : "VSS"; ….. }

Hình vẽ

Nếu là đầu vào của vi mạch

Thường là 1 giá trị tuyệt đối, cho trong specification của chip

set_input_transition 0.12 [get_ports A]

Nếu là đầu vào của một module trong chip

Có thể xác định thông qua điện trở ra (kênh) của cổng kích thích đầu vào đang xét

Lệnh DC

set_driving_cell -lib_cell OR3B [get_ports A]

set_driving_cell -lib_cell FD1 -pin Qn [get_ports A]

set_driving_cell -lib_cell tên_cell -pin tên_pin -library tên_lib [get_ports tên_port]

5.3.2.4 b) Điện dung tải ở đầu ra

Điện dung tải đầu ra sẽ ảnh hưởng tới thời gian chuyển giá trị của tín hiệu ra=> ảnh hưởng

tới độ trễ của mạch

Tải đầu ra càng lớn thì mạch càng chậm

Hình vẽ

Nếu là đầu ra của chip

Được cho trong specification của chip và là giá trị tuyệt đối

Lệnh DC

set_load [expr 30.0/1000] [get_ports B]

Nếu là đầu ra của module

Được xác định bằng số lượng cổng tối đa mà đầu ra đó sẽ kích thích

Hình vẽ

Lệnh DC

set_load [expr [load_of my_lib/inv1a0/A]*3] [get_ports B]

my_lib/inv1a0/A= tên thư viện/tên_cell/tên_pin

5.3.2.5 Chú ý: Khi các cổng kích thích đầu vào và tải đầu ra chưa biêt

Dùng Load Budget,xác định dự phòng cho thiết kế

Giả sử các đầu vào được kích thích bằng cell yếu nhất

set_driving_cell -no_design_rule -lib_cell inv1a1 $all_in_ex_clk

set all_in_ex_clk [remove_from_collection [all_inputs] [get_ports clk]

mỗi thư viện sẽ qui định 1 rule thiết kế riêng -no_design_rule là để tạm thời dc sẽ

không check rule

Đặt điện dung đầu vào lớn nhất là 10 cell and2

set MAX_INPUT_LOAD [expr load_of my_lib/and2a1/A] * 10] set_max_capacitance

$MAX_INPUT_LOAD $all_in_ex_clk

Đặt điện dung đầu ra lớn nhất là 3 khối 10 cell

set_load [expr $MAX_INPUT_LOAD * 3] [all_outputs]

Hình vẽ

Khi đầu vào được kích thích bằng FF, và đầu ra sẽ kích thích FF

Cổng kích thích đầu vào sẽ là pin Q/Qn của FF

Cổng tải đầu ra sẽ là pin D của FF

5.3.2.6 c) Điều kiện nhiệt độ/điện áp/công nghệ chế tạo

Chỉ ra trong file target_library

list_libs

Xem các file db đã được nạp

Xác định tên của thư viện.VD : cb13fs120_tsmc_max

report_lib

Xem các thông số trong 1 thư viên

Sử dụng lệnh để xuất ra file report

redirect -file lib.rpt { report_lib tên_thưuviện}

sh gedit lib.rpt

set_operating_conditions

Đặt thông số PVT trong thư viên

Xem phần operating conditions trong file lib.rpt

set_operating_conditions -max cb13fs120_tsmc_max

Hình vẽ

5.3.2.7 d) RC ký sinh trên đường dây nối

phụ thuộc kích thước thiết kế(chiều dài dây nối)

5.3.2.8 Tổng kết lệnh

5.3.3 5.3.3. Ví dụ cho Design Compiler

5.3.3.1 Spec

5.3.3.2 Schematic

5.3.3.3 MY_DESIGN.con

###################################

# #

# UNITS #

# #

###################################

# The unit of time in this library is 1ns

# The unit of capacitance in this library is 1pF

#

###################################

# #

# CLEAN-UP #

# #

###################################

# Remove any existing constraints and attributes

#

reset_design

###################################

# #

# CLOCK DEFINITION #

# #

###################################

# A 333Mhz clock is a 3.0ns period:

#

create_clock -period 3.0 [get_ports clk]

# External clock source latency is 700ps or 0.7ns

#

set_clock_latency -source -max 0.7 [get_clocks clk]

# The maximum internal clock network insertion delay or latency is 300ps or 0.3 ns:

#

set_clock_latency -max 0.3 [get_clocks clk]

# The +/-30ps internal clock delay variation to register clock pins results in a 60ps worst case skew or

uncertainty, if you launch

# late (+30ps) and capture early (-30ps)r; Add 40ps due to jitter and 50ps for setup margin;

# This equals 150ps or 0.15 ns of total uncertainty.

#

set_clock_uncertainty -setup 0.15 [get_clocks clk]

# uncertainty = 190ps

# The maximum clock transition is 120ps or 0.12ns

#

set_clock_transition 0.12 [get_clocks clk]

###################################

# #

# INPUT TIMING #

# #

###################################

# The maximum "input delay" (external) on ports data1 and data2 is:

# clock period - clock uncertainty - delay of S - register setup time =

# Wrong: 3.0 - 0.15 - 2.2 - 0.2 = 0.45ns

# Right: 3.0 - 0.19 - 2.2 - 0.2 = 0.41ns

set_input_delay -max 0.45 -clock clk [get_ports data*]

# The latest arrival time at port sel is ds1.4ns (absolute time). The total clock insertion delay or latency to the

external

# registers is 700ps + 300ps or 1.0ns. Therefore, the relative input delay on the port is 1.4 -1.0 = 0.4ns

#

set_input_delay -max 0.4 -clock clk [get_ports sel]

###################################

# #

# OUTPUT TIMING #

# #

###################################

# The output delay at port out1 is 420ps + 80ps = 500ps or 0.5ns

#

set_output_delay -max 0.5 -clock clk [get_ports out1]

# The internal delay to out2 is 810ps. The external capturing clock edge happens 3ns after the launch edge,

# minus the uncertainty of 0.15ns, or 2.85ns after launch. To constrain the internal delay to 0.81ns the

# output delay must therefore be constrained to 2.85ns - 0.81ns = 2.04ns.

#

set_output_delay -max 2.04 -clock clk [get_ports out2]

# The setup time requirement on port out3 is 400ps or 0.4ns with respect to the capturing register's clock.

# This is, by definition, the "set_output_delay" value

#

set_output_delay -max 0.4 -clock clk [get_ports out3]

###################################

# #

# COMBINATIONAL LOGIC TIMING #

# #

###################################

# The maximum delay through the combinational logic is 2.45ns. This can be constrained by pretending that

there are

# launching registers on the input ports Cin1 and Cin2 and capturing registers on the output port Cout, and

applying

# corresponding input and output delays. The sum of the external input and output delay values must be equal

to the

# clock period minus the clock uncertainty minus the maximum combo delay = 3ns - 0.15ns - 2.45ns = 0.4ns.

# This means that the input and output delay values can be 0.4 and 0.0, or 0.2 and 0.2, or 0.1 and 0.3, etc.,

respectively.

#

set_input_delay -max 0.3 -clock clk [get_ports Cin*]

set_output_delay -max 0.1 -clock clk [get_ports Cout]

###################################

# #

# ENVIRONMENTAL ATTRIBUTES #

# #

###################################

# All input ports, except clk and Cin, are driven by bufbd1 buffers

#

set_driving_cell -lib_cell bufbd1 -library cb13fs120_tsmc_max \

[remove_from_collection [all_inputs] [get_ports "clk Cin*"]]

# Port Cin is a chip level input and has an input transition of 120ps or 0.12 ns

#

set_input_transition 0.12 [get_ports Cin*]

# All outputs, except Cout, drive 2x bufbd7 loads

#

set_load [expr 2 * {[load_of cb13fs120_tsmc_max/bufbd7/I]}] [get_ports out*]

# Cout drives 25fF, or .025 pF

#

set_load 0.025 [get_ports Cout*]

# operating condition use to scale cell and net delays.

#

set_operating_conditions -max cb13fs120_tsmc_max

5.4 5.4. Cơ sở quá trình tổng hợp

5.4.1 5.4.1 Quá trình tổng hợp

5.4.1.1 Hình vẽ

5.4.1.2 B1: Tổng hợp mức kiến trúc (mức cao)

5.4.1.3 B2: Tổng hợp mức logic không phụ thuộc công nghệ

5.4.1.4 B3: Tổng hợp mức cổng và ánh xạ công nghệ

5.4.1.5 Thuật toán tổng hợp tìm cách tối thiểu hóa diện tích trong khi thỏa mãn các điều

kiện giới hạn thời gian và các điều kiện khác

Tìm mạch có hiệu năng (tốc độ) vừa đủ và có diện tích nhỏ nhât

5.4.1.6 Để đạt được kết quả tổng hợp tốt

Code RTL được viết tốt, tối ưu cho phần mềm tổng hợp (Xem chương 6)

Code RTL tuân theo kiểu viết code của DC và phụ thuộc kinh nghiệm

Thuật toán được viết hiệu quả với phần cứng

Các điều kiện giới hạn được đặt đủ, và chính xác

Các điều kiện giới hạn và tính chất môi trường đặt thực tế, không quá chặt

Tất cả các đường tín hiệu được xác định

5.4.2 5.4.2. Một số kỹ thuật tổng hợp

5.4.2.1 Tối ưu phép toán số học

Tối giản hằng số và toán hạng

A+2*B-2+B-A+7 = 3*B + 5

Chia sẻ các biểu thức con

Z1 = A+B+C; Z2=C+D+B=> T=B+C; Z1=A+T;Z2=T+D;

Biến đổi SOP thành POS

A*C+B*C=(A+B)*C

Chia sẻ biểu thức so sánh

Z1=A>B;Z2=A<B;Z3=A<=B;

Dùng một bộ trừ

Tối ưu các phép nhân với hằng số

Temp =In1+In2; Out1=Temp*105 (64+32+8+1) Out2=Temp*621 (105+512+4) Out1 =

Temp<<6 + Temp<<5+Temp<<3+Temp Out2 = Out1+Temp<<9+Temp<<2

5.4.2.2 Chia sẻ tải và nhân bản cổng logic

Trước tối ưu

Sau tối ưu

Nhân bản các cổng logic điều khiển (kích thích) nhiều đầu ra và nằm trên đường tín hiệu

chậm nhất sẽ giúp giảm tải của cổng logic và tăng tốc độ đường tín hiệu chậm nhất

5.4.2.3 Tối ưu qua đường biên

Trước tối ưu

Sau tối ưu

Lan truyền hằng số, các cổng không kết nối, các bộ đảo để giảm trễ hoặc/và diện tích

5.4.2.4 Định thời thích nghi (Adaptive Retiming)

Trước

Sau

Retiming: thay đổi thời gian hoạt động của các tín hiệu bên trong mạch bằng cách di chuyển

các thanh ghi

Chú ý: Retiming không được làm thay đổi thời gian hoạt động của tín hiệu đầu vào/đầu ra

5.4.2.5 Định thời thanh ghi (Register Retiming)

always @(posedge clk) y <= a*b+c*d+e-f

Tổng hợp

Sử dụng thanh ghi pipeline

always @(posedge clk) begin prodAB <= a*b; prodCD <= c*d; diffEF <= e-f; p2_1 <=

prodAB+prodCD; p2_2 <= diffEF; y <= p2_1+p2_2;

Tổng hợp

Độ trễ là độ trễ của giai đoạn pipeline chậm nhất (bộ nhân)

Kỹ thuật

Di chuyển thanh ghi

Chia tách

Ghép

Hình vẽ

5.5 5.5. Phân tích kết quả tổng hợp

5.5.1 Kiểm tra sự vi phạm điều kiện thời gian

5.5.1.1 Xem xét các đường tín hiệu có slack <0

5.5.2 Sử dụng các kỹ thuật Timing Analysis

5.5.2.1 Tham khảo thêm tài liệu của Synopsys

5.6 Bài tập ví dụ

5.6.1 Thiết kế và tổng hợp vi mạch tuân theo chỉ tiêu kỹ thuật của chip: Cd54hc192

6 Chương 6. Nâng cao

6.1 6.1. Các bộ đếm, dịch, quay

6.1.1 6.1.1 Bộ đếm

6.1.1.1 Hình vẽ

6.1.1.2 Mã

module cnt(clk,rst_n,en,cnt); input clk,rst_n; output [7:0] cnt; reg [7:0] cnt; always

@(posedge clk or negedge rst_n) if (!rst_n) cnt <= 8’h00; else if (en) cnt <= cnt + 1; //

combinational endmodule

6.1.1.3 Kết quả tổng hợp

6.1.2 6.1.2 Bộ đếm vòng

6.1.2.1 Mã

module ring_counter (count, enable, clock, reset_n); output reg [7: 0] count; input enable,

reset, clock; always @ (posedge clock or negedge reset_n) if (!reset_n) count <=

8'b0000_0001; else if (enable == 1'b1) count <= {count[6:0], count[7]}; endmodule

6.1.2.2 Kết quả tổng hợp

6.1.3 6.1.3 Bộ quay

6.1.3.1 Mã

module rotator (Data_out, Data_in, load, clk, rst_n); output reg [7: 0] Data_out; input [7: 0]

Data_in; input load, clk, rst_n; always @ (posedge clk or negedge rst_n) if (!rst_n) Data_out <=

8'b0; else if (load) Data_out <= Data_in; else if (en) Data_out <= {Data_out[6: 0], Data_out[7]};

else Data_out <= Data_out endmodule

6.1.3.2 Kết quả tổng hợp

6.1.4 6.1.4 Bộ dịch

6.1.4.1 Mã

always @ (posedge clk) begin if (rst) Data_Out <= 0; else case (select[1:0]) 2’b00:

Data_Out <= Data_Out; // Hold 2’b01: Data_Out <= {Data_Out[3], Data_Out[3:1]}; // ÷ by 2

2’b10: Data_Out <= {Data_Out[2:0], 1’b0}; // X by 2 2’b11: Data_Out <= Data_In; // Parallel

Load endcase end endmodule

6.1.4.2 Kết quả tổng hợp

6.1.5 6.1.5 Tham số hóa

6.1.5.1 parameter

Định nghĩa hằng số bên trong module

Có thể truyền như 1 tham số khi instantiate module

6.1.5.2 localparam

Định nghĩa hằng số trong module

Không truyền như tham số khi instantiate module

6.1.5.3 Ví dụ 6.1.5

module adder(a,b,cin,sum,cout); parameter WIDTH = 8; // default is 8 input [WIDTH-1:0] a,b;

input cin; output [WIDTH-1:0] sum; output cout; assign {cout,sum} = a + b + cin endmodule

module alu(src1,src2,dst,cin,cout); input [15:0] src1,src2; …

////////////////////////////////// // Instantiate 16-bit adder //

//////////////////////////////// adder #(16) add1(.a(src1),.b(src2),

.cin(cin),.cout(cout), .sum(dst)); … endmodule

6.1.5.4 Ví dụ 6.1.6

module register2001 #(parameter SIZE=8) (output reg [SIZE-1:0] q, input [SIZE-1:0] d, input

clk, rst_n); always @(posedge clk, negedge rst_n) if (!rst_n) q <= 0; else q <= d; endmodule

6.2 6.2. Mô tả máy trạng thái hữu hạn FSM

6.2.1 6.2.1. Khái niệm FSM

6.2.1.1 Hình vẽ

6.2.1.2 FSM được triển khai bằng mạch logic tuần tự gồm 2 khối cơ bản

Khối logic tổ hợp mô tả hàm trạng thái kế tiếp và hàm đầu ra

Khối FF lưu trữ trạng thái hiện tại của mạch

6.2.1.3 FSM được mô tả hoạt động bằng đồ thị chuyển trạng thái hoặc bảng chuyển trạng

thái

6.2.2 6.2.2. Mô tả FSM trong Verilog

6.2.2.1 Mô tả logic tổ hợp và FF riêng rẽ

6.2.2.2 Logic tổ hợp được mô tả bằng khối always và phép gán blocking

Thường sử dụng kèm lệnh case, trong đó mỗi case item là 1 trạng thái

6.2.2.3 FF được mô tả bằng khối always có clock và phép gán non-blocking

6.2.2.4 Chú ý: tránh latch

Khối case luôn cần nhánh default

Có thể gán giá trị mặc định cho đầu ra và thanh ghi trạng thái kế tiếp trước khối case, if/else

6.2.3 Ví dụ 6.2.1

6.2.3.1 Hình vẽ

6.2.3.2 Mã 1

module fsm(clk,rst,a,b,Y,Z); input clk,rst,a,b; output Y,Z; reg Y, Z; localparam S0 = 2'b00,

S1 = 2'b01, S2 = 2'b10; reg [1:0] state,nxt_state; always @(posedge clk, posedge rst) if

(rst) state <= S0; else state <= nxt_state; always @ (state,a,b) case (state) S0 : if (a) begin

nxt_state = S1; Z = 1; end else nxt_state = S0; S1 : begin Y=1;

if (b) begin nxt_state = S2; Z=1; end else nxt_state = S1; end

S2 : nxt_state = S0; endcase endmodule

6.2.3.3 Kết quả tổng hợp

6.2.3.4 Mã 2

6.2.4 6.2.3. Mô tả các máy trạng thái tương tác với nhau

6.2.4.1 Ví dụ khi cần đợi ở một trạng thái trong khoảng thời gian xác định

Máy trạng thái tương tác với bộ đếm

6.2.4.2 Đầu ra của một FSM được dùng để điều khiển một FSM khác và ngược lại.

Thường sử dụng kiểu liên lạc bắt tay

6.2.4.3 Ví dụ 6.2.2

Đồ thị chuyển trạng thái

Biểu đồ thời gian toàn mạch

Biểu đồ thời gian tương tác giữa FSM và bộ đếm

Sơ đồ khối mạch

module eeprom(clk,rst_n,wrt_eep, wrt_data,eep_r_w_n,eep_cs_n, eep_bus,chrg_pmp_en);

parameter IDLE=2'b00, BUS=2'b01, CHRG=2'b10; input clk,rst_n,wrt_eep; input [11:0] wrt_data; //

data to write output eep_r_w_n,eep_cs_n; output chrg_pmp_en; // hold for 3ms inout [11:0] eep_bus;

wire eep_r_w_n,eep_cs_n; reg chrg_pmp_en; // hold for 3ms reg [13:0] tm; // 3ms => 14-bit timer

reg clr_tm,inc_tm,bus_wrt; reg [1:0] state,nxtState; //// implement 3ms timer below //// always

@(posedge clk or posedge clr_tm) if (clr_tm) tm <= 14'h0000; else if (inc_tm) tm <= tm+1; ////

@4MHZ cnt of 2EE0 => 3ms //// assign tm_eq_3ms = (tm==14'h2EE0)?1'b1 : 1'b0; //// implement

state register below //// always @(posedge clk or negedge rst_n) if (!rst_n) state <= IDLE; else

state <= nxtState; //// state transition logic & //// //// output logic //// always

@(state,wrt_eep,tm_eq_3ms) begin nxtState = IDLE; // default all bus_wrt = 0; // to avoid

clr_tm = 0; // unintended inc_tm = 0; // latches chrg_pmp_en = 0; case (state)

IDLE : if (wrt_eep) nxtState = BUS; BUS : begin clr_tm = 1; bus_wrt = 1; nxtState =

CHRG; end default : begin // is CHRG inc_tm = 1; chrg_pmp_en=1; if (tm_eq_3ms)

begin nxtState = IDLE; end else nxtState = CHRG; end endcase end

assign eep_r_w_n = ~bus_wrt; assign eep_cs_n = ~bus_wrt; assign eep_bus = (bus_wrt) ? wrt_data :

12'bzzz; endmodule

Kết quả tổng hợp

Mạch

6.2.5 6.2.4. Thiết kế mạch điều khiển và đường dữ liệu: FSMD/ASMD

6.2.5.1 Các mạch xử lý tín hiệu (ví dụ trong thông tin/viễn thông) cần xử lý và dịch chuyển

một lượng lớn dữ liệu bằng các phép toán lặp đi lặp lại

6.2.5.2 Các mạch tuần tự xử lý dữ liệu thường được chia làm hai phần

Đường dữ liệu

Bao gồm các tài nguyên tính toán (như bộ cộng, nhân, dịch...) các thanh ghi lưu trữ dữ liệu,

các khối logic dùng để dịch chuyển dữ liệu giữa các khối tính toán, thanh ghi, và môi trường

Đường dữ liệu thực hiện các thao tác tính toán lặp lại trên các bộ dữ liệu khác nhau

Được mô tả bằng đồ thị dòng dữ liệu thể hiện các bước tính toán tuần tự dữ liệu

Khối điều khiển

Làm một FSM thực hiện việc điều phối các thao tác tính toán trong đường dữ liệu

Thực hiện việc điều phối, đồng bộ hoạt động của đường dữ liệu (hoạt động của các

khối chức năng trong đường dữ liệu)

Tạo ra các tín hiệu nạp, đọc, dịch chuyển nội dung các thanh ghi

Đọc lệnh/dữ liệu từ bộ nhớ

Ghi dữ liệu vào bộ nhớ

Điều hướng dữ liệu qua các bộ mux

Điều khiển các cổng 3 trạng thái

Điều khiển hoạt động của khối ALU hay các khối xử lý dữ liệu phức tạp

Được mô tả bằng đồ thị chuyển trạng thái, hoặc Algorithmic-State Machine

Hình vẽ

6.2.5.3 Phân chia mạch thành 2 phần giúp làm rõ kiến trúc và đơn giản hóa việc thiết kế

6.2.5.4 FSMD, ASMD được dùng để miêu tả hoạt động của thiết kế được chia thành 2 phần

đường dữ liệu và khối điều khiển

FSMD là sự kết hợp của đồ thị chuyển trạng thái STG và đồ thị dòng dữ liệu

Trong FSMD, các hoạt động của đường dữ liệu được thể hiện trên các đường chuyển trạng

thái

ASM là dạng đặc biệt của lưu đồ thuật toán

Gồm các khối kết nối với nhau. Mỗi khối gồm 3 node

Trạng thái: Thể hiện trạng thái của mạch

Quyết định: Thể hiện điều kiện chuyển trạng thái của mạch phụ thuộc đầu vào

Điều kiện: Thể hiện đầu ra của mạch

Hình vẽ

ASMD được tạo ra từ ASM bằng cách gắn các hoạt động của đường dữ liệu với các đường nối

giữa các trạng thái. Các hoạt động này xảy ra khi phần điều khiển chuyển từ trạng thái này sang

trạng thái khác tương ứng

6.2.5.5 Các bước để thiết kế mạch điều khiển và đường dữ liệu

Đầu vào: Lưu đồ thuật toán mô tả hoạt động của mạch

Đầu ra: Kiến trúc đường dữ liệu và ASMD mô tả hoạt động của đường dữ liệu và khối điều

khiển

B1: Thiết kế đường dữ liệu

B1a) Xác định các phép toán (hoạt động) của đường dữ liệu dựa trên các phép toán có trong

lưu đồ thuật toán

B1b) Xác định các khối chức năng phần cứng cần có để thực hiện các phép toán

B1c) Kết nối các khối chức năng phần cứng thành đường dữ liệu thể hiện dòng dịch chuyển

của dữ liệu cần được xử lý như lưu đồ thuật toán

B1d) Xác định đầu vào điều khiển và đầu ra trạng thái của đường dữ liệu

B2: Thiết kế khối điều khiển

B2a) Chuyển đổi lưu đồ thuật toán thành ASM

B2b) Gắn các hoạt động của đường dữ liệu với ASM

6.2.5.6 Ví dụ 6.2.2

Thiết kế bộ đếm up/down dùng FSMD

6.2.5.7 Ví dụ 6.2.3

Thiết kế bộ nhân nối tiếp

module serial_mult #(parameter n=8) (input clk, rst_n, input load, input [n-1:0] a, input [n-

1:0] b, output [2*n-1:0] c); wire b0, adder_control, load_control, compute_control; wire [n-1:0] i;

data_unit #(.n(n)) datapath (.clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c),

.load_control(load_control), .adder_control(adder_control), .compute_control(compute_control),

.i(i), .b0(b0) ); control_unit #(.n(n)) control (.clk(clk), .rst_n(rst_n), .load(load), .b0(b0),

.i(i), // status signal from datapath .load_control(load_control), // control signal to datapath

.adder_control(adder_control), .compute_control(compute_control) ); endmodule module

data_unit #(parameter n=8) (input clk, rst_n, input [n-1:0] a, b, output reg [2*n-1:0] c, input

load_control, adder_control, compute_control, output b0, output reg [n-1:0] i ); reg [n-1:0] Rb; reg

[n-1:0] Ra; reg [2*n:0] tmp; reg carry; assign b0 = Rb[0]; assign tmp = (adder_control==1)?(c[2*n-

1:n]+Ra):c; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin Ra <= 0; Rb <= 0; c <=

0; i <= 0; carry <= 0; end else begin if (load_control) begin Ra[n-1:0] <= a; Rb <= b; i <= 0;

c <= 0; carry <= 0; end else begin if (compute_control) begin Rb <= {1'b0, Rb[n-1:1]}; // dich

phai Rb c <= {tmp[2*n:1]}; // dich phai tmp i <= i+1; end end end end endmodule module

control_unit # (parameter n=8) ( input clk, rst_n, input load, input [n-1:0] i, input b0, output reg

load_control, adder_control, compute_control); localparam idle = 1'b0; localparam computing =

1'b1; reg current_state, next_state; always @(posedge clk or negedge rst_n) begin if (!rst_n)

current_state <= idle; else current_state <= next_state; end always @(current_state, load, i, b0)

begin next_state = idle; load_control = 0; adder_control = 0; compute_control = 0; case

(current_state) idle: if (load) begin next_state = computing; load_control = 1; end

computing: if (i==n) next_state = idle; else begin compute_control = 1; adder_control = b0;

next_state = computing; end endcase end endmodule

6.3 6.3. Các câu lệnh nâng cao

6.4 6.4. Hướng dẫn code của phần mềm tổng hợp Synopsys

6.4.1 Các kiểu viết code khác nhau sẽ cho kết quả tổng hợp khác nhau

6.4.2 Phần mềm tổng hợp không thể tự tối ưu mã nguồn RTL tồi

6.4.3 Hiểu cách phần mềm tổng hợp biên dịch mã RTL sẽ giúp có được kết quả tổng hợp

tốt

6.4.4 6.5.1. Dùng chung tài nguyên

6.4.4.1 Phần mềm tổng hợp có thể sử dụng 1 bộ tài nguyên số học cho các câu lệnh trong

if/case để đạt được thiết kế nhỏ nhất mà vẫn thỏa mãn điều kiện thời gian

6.4.4.2 Tối ưu tài nguyên dùng chung được thực hiện khi tối ưu mức kiến trúc.

6.4.4.3 Việc quyết định có chia sẻ hay không tài nguyên phụ thuộc

Cách viết code

Chỉ các phép toán trong cùng if/case có thể chia sẻ tài nguyên

Giới hạn

Chia sẻ tài nguyên chỉ xảy ra khi không vi phạm điều kiện giới hạn thời gian

6.4.4.4 Ví dụ:

Kết quả tổng hợp

6.4.4.5 Có thể viết mã để không cho phép hoặc luôn yêu cầu chia sẻ tài nguyên

6.4.5 6.5.2. Thay đổi thứ tự toán hạng

6.4.5.1 Phần mềm tổng hợp có thể thay đổi thứ tự thực hiện phép toán để thỏa mãn giới

hạn thời gian

Thứ tự sẽ không thay đổi nếu sử dụng dấu ngoặc đơn để bắt buộc thứ tự thực hiện

6.4.5.2 Ví dụ

Kết quả tổng hợp

6.4.6 6.5.3. For loop

7 Các kiến thức cần thiết

7.1 Lập trình Verilog

7.1.1 Mạch logic tổ hợp

7.1.1.1 always

7.1.1.2 If else

7.1.1.3 Assign

blocking, non-blocking assignment

7.1.1.4 Độ trễ trong mạch logic tổ hợp

7.1.2 Mạch tuần tự

7.1.2.1 always with clock

7.1.2.2 reset

7.1.2.3 case

7.1.2.4 Moore/Mealy

7.1.2.5 Setup/Hold time

7.1.2.6 Xác định tần số đồng hồ

7.1.2.7 Flip-Flop

7.1.3 Lập trình FSMD/ASM

7.2 Tổng hợp mạch (Synthesis)

7.2.1 Cấu trúc ASIC

7.2.1.1 Tổng hợp ra gate netlist dùng Synopsys

7.2.1.2 Phân tích timing

7.2.2 Cấu trúc FPGA

7.2.2.1 Tổng hợp mạch lên board Altera DE2

7.2.2.2 Kết nối mạch Altera DE2 với Simulink/Matlab

7.2.3 Các thuật toán tổng hợp mạch cơ bản

7.2.4 Khái niệm timing

7.2.5 Khái inệm Datapath optimization khi dùng HDL và khi synthesis

7.3 Layout mạch

7.3.1 Cấu trúc CMOS

7.3.2 Clock tree

7.3.3 Standard cell

7.3.4 Power supply

8 Mục đích môn học

8.1 Thiết kế mạch số dùng ngôn ngữ mô tả phần cứng Verilog HDL

8.2 Xây dựng testbench tự kiểm tra thiết kế phần cứng

8.2.1 Mô phỏng HDL

8.2.2 Kiểm chứng thiết kế số

8.3 Tông hợp dòng dữ liệu và thiết kế hành vi (behavior)

8.4 Khái niệm cơ bản về phân tích thời gian (Timing analysis)

8.5 Tối ưu thiết kế phần cứng (thời gian, diện tích, năng lượng)

8.6 Suy nghĩ kiểu phần cứng!!!

9 Yêu cầu kiến thức

9.1 Biểu diễn số

9.1.1 Nhị phân, hệ 16

9.1.2 Có dấu

9.1.2.1 Mã bù 2

9.1.3 Không dấu

9.2 Đại số Bool

9.3 Thiết kế mạch ở mức cổng logic

9.3.1 Tối ưu mạch bằng bìa Karnaugh

9.4 Máy trạng thái hữu hạn (FSM)

9.4.1 Máy More

9.4.2 Máy Mealy

9.4.3 Triển khai máy trạng thái hữu hạn bằng logic tổ hợp

9.4.3.1 Phương pháp tối ưu máy bằng cách tìm trạng thái tương đương

9.4.3.2 Phương pháp mã hóa trạng thái

10 Tài liệu tham khảo

10.1 Advanced Digital Design Verilog HDL, Michael D. Ciletti.

10.2 IEEE Standard Verilog Hardware Description Language, IEEE, Inc., 2001

10.3 IEEE Standard for Verilog Register Transfer Level Synthesis, IEEE, Inc.,

2002

10.4 Digital Design and Computer Architecture, David Money Harris

10.5 Bài giảng của Eric Hoffman

11 Công cụ phần mềm thực hành

11.1 Modelsim HDL Simulation Tools (Mentor)

11.1.1 http://model.com/content/modelsim-pe-student-edition-hdl-simulation

See document(s): modelsim-pe-student-edition-hdl-simulation

11.2 Công cụ tổng hợp IC: Synopsys - Design Compiler

11.3 Công cụ tổng hợp FPGA: Quartus II Web Edition Software

11.3.1 https://www.altera.com/download/software/quartus-ii-we

See document(s): quartus-ii-we

12 Điểm số

12.1 Giữa kỳ 30%

12.1.1 20%: Bài tập lớn

12.1.1.1 Originality

12.1.1.2 Workload

12.1.1.3 Funny

12.1.2 10%: Câu hỏi & Trả lời

12.2 Cuối kỳ: 70%

12.3 10%: Điểm thưởng

13 Thời gian & Địa điểm

13.1 Thứ 3,14h15-17h20, TC305

13.2 Thứ 4, 7h35-11h50, D6-101