HDLBits Tutorial
Getting Started⚓︎
Getting Started⚓︎
Website: https://hdlbits.01xz.net/wiki/Step_one
這題是教你怎麼操作平台的,然後要對one輸出1。這裡有個細節是給值時盡量寫的清楚一點,像這裡1bit,就可以不是只給1,而是給1'b1。
Output Zero⚓︎
Website: https://hdlbits.01xz.net/wiki/Zero
這題跟上題大同小異,只是換成輸出0。
module top_module(
output zero
);// Module body starts after semicolon
assign zero = 1'b0;
endmodule
Verilog Language⚓︎
Basics⚓︎
Simple wire⚓︎
Website: https://hdlbits.01xz.net/wiki/Wire
這題就是簡單的把out和in接在一起。
Four wires⚓︎
Website: https://hdlbits.01xz.net/wiki/Wire4
這題就照著圖接線,w和a相接,xy和b相接,z和c相接。
module top_module(
input a,b,c,
output w,x,y,z );
assign w = a;
assign x = b;
assign y = b;
assign z = c;
endmodule
Inverter⚓︎
Website: https://hdlbits.01xz.net/wiki/Notgate
這題要寫一個not gate。
值得注意的是,verilog中有分bitwise operator和logical operator,bitwise operator就是對input的每個bit都做相對的運算,所以最後輸出的bit數會跟input一樣。而logical operator只會邏輯上做運算,最後只會輸出1 bit。
所以說bitwise not符號是~
,而logical not符號是!
,雖然這題input只有1 bit沒差,不過細節可能要注意。
AND gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Andgate
這題就刻一個and gate,跟上題差不多,要注意的是bitwise and符號是&
,而logical and符號是&&
,
NOR gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Norgate
這題就刻一個nor gate,跟上題差不多,要注意的是bitwise or符號是~
,而logical and符號是~~
,
XNOR gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Xnorgate
這題就刻一個xnor gate,跟上題差不多,要注意的是bitwise xor符號是^
,而verilog中沒有logical xor運算。
Declaring wires⚓︎
Website: https://hdlbits.01xz.net/wiki/Wire_decl
這題引入了wire的概念,wire就是在線路複雜時,提供節點來幫助閱讀。補充一下,input和output本身就是wire。
`default_nettype none
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
wire a_and_b, c_and_d;
assign a_and_b = a & b;
assign c_and_d = c & d;
assign out = a_and_b | c_and_d;
assign out_n = ~out;
endmodule
7458 chip⚓︎
Website: https://hdlbits.01xz.net/wiki/7458
這題跟上題類似,就是線路稍微複雜,可以直接寫,也可以使用wire幫助閱讀。
module top_module (
input p1a, p1b, p1c, p1d, p1e, p1f,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
assign p1y = (p1a & p1b & p1c) | (p1d & p1e & p1f);
assign p2y = (p2a & p2b) | (p2c & p2d);
endmodule
Vectors⚓︎
Vectors⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector0
這題是將[2:0] vec分別賦值給[2:0] outv和{o2,o1,o0},補充說明,assign {o2,o1,o0} = vec;
等價於assign o2 = vec[2]; assign o1 = vec[1]; assign o0 = vec[0];
。
module top_module (
input wire [2:0] vec,
output wire [2:0] outv,
output wire o2,
output wire o1,
output wire o0 ); // Module body starts after module declaration
assign outv = vec;
assign {o2,o1,o0} = vec;
endmodule
Vectors in more detail⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector1
跟上題大同小異,assign {out_hi,out_lo} = in;
等價於assign out_hi = in[15:8]; assign out_lo = in[7:0];
。
`default_nettype none // Disable implicit nets. Reduces some types of bugs.
module top_module(
input wire [15:0] in,
output wire [7:0] out_hi,
output wire [7:0] out_lo );
assign {out_hi,out_lo} = in;
endmodule
Vector part select⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector2
跟上題大同小異,assign out = {in[7:0],in[15:8],in[23:16],in[31:24]};
等價於assign out[31:24] = in[ 7: 0]; assign out[23:16] = in[15: 8]; assign out[15: 8] = in[23:16]; assign out[ 7: 0] = in[31:24];
。
module top_module(
input [31:0] in,
output [31:0] out );
assign out = {in[7:0],in[15:8],in[23:16],in[31:24]};
endmodule
Bitwise operators⚓︎
Website: https://hdlbits.01xz.net/wiki/Vectorgates
這題主要講述bitwise operators和logical operators的差異。像說bitwise or的符號為|
,logical or的符號為||
,bitwise not的符號為~
,logical not的符號為!
。這題的not是bitwise not,不要弄混了。
module top_module(
input [2:0] a,
input [2:0] b,
output [2:0] out_or_bitwise,
output out_or_logical,
output [5:0] out_not
);
assign out_or_bitwise = a | b;
assign out_or_logical = a || b;
assign out_not = ~ {b,a};
endmodule
Four-input gates⚓︎
Website: https://hdlbits.01xz.net/wiki/Gates4
這題在複習各種gate的用法。
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = in[3] & in[2] & in[1] & in[0];
assign out_or = in[3] | in[2] | in[1] | in[0];
assign out_xor = in[3] ^ in[2] ^ in[1] ^ in[0];
endmodule
Vector concatenation operator⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector3
這題在教concatenation的概念,然後因為題目要求要padding11在最右邊2bits,所以要加上2'b11。
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
assign {w,x,y,z} = {a,b,c,d,e,f,2'b11};
endmodule
Vector reversal 1⚓︎
Website: https://hdlbits.01xz.net/wiki/Vectorr
這題當然能用concatenation的概念完成,當然如果想寫個類似for loop的方法連線,可以參考generate語法。
module top_module(
input [7:0] in,
output [7:0] out
);
generate
genvar i;
for (i=0; i<8; i = i+1) begin: my_block_name
assign out[i] = in[8-i-1];
end
endgenerate
endmodule
Replication operator⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector4
這題將8bit轉成32bit,並且多餘的24bit要填入in[7],所以語法如下。
module top_module (
input [7:0] in,
output [31:0] out );//
assign out = { { 24{ in[7] } },in};
endmodule
More replication⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector5
這題也是練習replication,aaaaabbbbbcccccdddddeeeee可以寫成{ {5{a}},{5{b}},{5{c}},{5{d}},{5{e}}}
,abcdeabcdeabcdeabcdeabcde可以寫成{5{a,b,c,d,e}}
。
module top_module (
input a, b, c, d, e,
output [24:0] out );//
assign out = ~({ { 5{a} },{5{b}},{5{c}},{5{d}},{5{e}}} ^ {5{a,b,c,d,e}});
endmodule
Modules: Hierarchy⚓︎
Modules⚓︎
Website: https://hdlbits.01xz.net/wiki/Module
這題在教如何引用module。
module top_module ( input a, input b, output out );
mod_a moda(.out(out),.in1(a),.in2(b));
endmodule
Connecting ports by position⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_pos
這題跟上題差不多,題目要求我們照著argument的位置接線。
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
module mod_a ( out1, out2, a, b, c, d );
endmodule
Connecting ports by name⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_name
這題跟上題差不多,只是上題是要求根據argument的位置接線,這題是要求跟據argument的名字接線。
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a moda(.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));
endmodule
Three modules⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_shift
這題是練習用接線的方式,將3個dff串接在一起。
module top_module ( input clk, input d, output q );
wire q1,q2;
my_dff dff1( .clk(clk), .d(d), .q(q1));
my_dff dff2( .clk(clk), .d(q1), .q(q2));
my_dff dff3( .clk(clk), .d(q2), .q(q));
endmodule
Modules and vectors⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_shift8
這題跟上題差不多,只是後面多接了一個multiplexer。而multiplexer可以用always block實現,速度會比用if else還快,而因為multiplexer是combinational logic,所以要用blocking assignments。
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0]q1,q2,q3;
my_dff8 dff1( .clk(clk), .d(d), .q(q1));
my_dff8 dff2( .clk(clk), .d(q1), .q(q2));
my_dff8 dff3( .clk(clk), .d(q2), .q(q3));
always @(*)
case(sel)
2'b00: q = d;
2'b01: q = q1;
2'b10: q = q2;
2'b11: q = q3;
endcase
endmodule
Adder 1⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_add
這題單純把兩個16bit adder接在一起,值得注意的是,如果argument不想接線,直接留空就行了。
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire c1;
add16 add_1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(c1));
add16 add_2( .a(a[31:16]), .b(b[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule
Adder 2⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_fadd
這題跟上題差不多,只是要多寫一個1 bit full adder,可以用concatenation來實現。
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire c1;
add16 add_1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(c1));
add16 add_2( .a(a[31:16]), .b(b[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
assign {cout, sum} = a + b + cin;
endmodule
Carry-select adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_cseladd
這題要我們接線CSA(carry-select adder),CSA的好處在於已經偷算完cin是0和1的case,等到低位元進位後,就能馬上用multiplexer輸出算好的結果,缺點就是因為同時要算cin是0和1的結果,面積會變兩倍。
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire sel;
wire [15:0] s1,s2;
add16 add1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(sel));
add16 add2( .a(a[31:16]), .b(b[31:16]), .cin(1'b0), .sum(s1), .cout());
add16 add3( .a(a[31:16]), .b(b[31:16]), .cin(1'b1), .sum(s2), .cout());
always @(*)
case(sel)
1'b0: sum[31:16] = s1;
1'b1: sum[31:16] = s2;
endcase
endmodule
Adder-subtractor⚓︎
Website: https://hdlbits.01xz.net/wiki/Module_addsub
這題在教如何快速實現減法,也就是a - b = a + ~(b) + 1
這件事。
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire c1;
wire [31:0] b_xor;
assign b_xor = b ^ {32{sub}};
add16 add_1( .a(a[15:0]), .b(b_xor[15:0]), .cin(sub), .sum(sum[15:0]), .cout(c1));
add16 add_2( .a(a[31:16]), .b(b_xor[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule
Procedures⚓︎
Always blocks (combinational)⚓︎
Website: https://hdlbits.01xz.net/wiki/Alwaysblock1
這題在講說combinational logic可以有assign和always @(*)兩種寫法。然後有個細節要注意,assign的左值要用wire,always的左值要用reg,雖然這兩者在合成電路後沒差。
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b;
always @(*)
out_alwaysblock = a & b;
endmodule
Always blocks (clocked)⚓︎
Website: https://hdlbits.01xz.net/wiki/Alwaysblock2
這題就是在講combinational logic和sequential logic的差別。如果是clock always的話,最好賦值使用non-blocking。
// synthesis verilog_input_version verilog_2001
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign = a ^ b;
always@(*)
out_always_comb = a ^ b;
always@(posedge clk)
out_always_ff <= a ^ b;
endmodule
If statement⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_if
這題分別要求要寫三元運算和在combinational block中寫if/else,可能要注意的是cond可以共用。
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
wire cond;
assign cond = sel_b1 & sel_b2;
assign out_assign = cond ? b : a;
always@(*)begin
if(cond)begin
out_always = b;
end
else begin
out_always = a;
end
end
endmodule
If statement latches⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_if2
這題在講說要寫清楚else和default,不然verilog會合成出latch。
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 1'b0;
end
endmodule
Case statement⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_case
這題在教case如何使用,然後要記得寫default防止latch。
// synthesis verilog_input_version verilog_2001
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
always@(*) begin // This is a combinational circuit
case(sel)
3'b000: out = data0;
3'b001: out = data1;
3'b010: out = data2;
3'b011: out = data3;
3'b100: out = data4;
3'b101: out = data5;
default: out = 4'b0000;
endcase
end
endmodule
Priority encoder⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_case2
這題要寫一個encoder,我看了卡諾圖後,發現用if else或卡諾圖畫的沒什麼太大的差異,卡諾圖的gate level少了一點,但是gate多了一些,所以這題練習用if else寫。
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*)begin
if(in[0]) pos = 2'b00;
else if(in[1]) pos = 2'b01;
else if(in[2]) pos = 2'b10;
else if(in[3]) pos = 2'b11;
else pos= 2'b00;
end
endmodule
Priority encoder with casez⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_casez
這題跟上題差不多,只是嘗試用casez實作encoder。
// synthesis verilog_input_version verilog_2001
module top_module (
input [7:0] in,
output reg [2:0] pos );
always@(*)begin
casez(in)
8'bzzzzzzz1: pos = 3'b000;
8'bzzzzzz10: pos = 3'b001;
8'bzzzzz100: pos = 3'b010;
8'bzzzz1000: pos = 3'b011;
8'bzzz10000: pos = 3'b100;
8'bzz100000: pos = 3'b101;
8'bz1000000: pos = 3'b110;
8'b10000000: pos = 3'b111;
default: pos = 3'b000;
endcase
end
endmodule
Avoiding latches⚓︎
Website: https://hdlbits.01xz.net/wiki/Always_nolatches
這題在練習如何在有大量output情形時,透過預先寫默認的輸入來減少行數,而這種寫法對於合成電路沒什麼影響,因為實際的電路不是照著程式碼一行一行執行。
// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always@(*)begin
up = 1'b0;
down = 1'b0;
left = 1'b0;
right =1'b0;
case(scancode)
16'he06b: left= 1'b1;
16'he072: down= 1'b1;
16'he074: right= 1'b1;
16'he075: up= 1'b1;
endcase
end
endmodule
More Verilog Features⚓︎
Conditional ternary operator⚓︎
Website: https://hdlbits.01xz.net/wiki/Conditional
這題在教三元運算的使用。題目說要做一個4-to-1 MUX,可以簡單用3個2元運算接出電路。
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
wire [7:0]w1,w2;
assign w1 = (a<b)? a : b;
assign w2 = (c<d)? c : d;
assign min = (w1<w2)? w1 : w2;
endmodule
Reduction operators⚓︎
Website: https://hdlbits.01xz.net/wiki/Reduction
這題練習reduction operator,透過assign parity =^in
,省去了冗長的in運算。
Reduction: Even wider gates⚓︎
Website: https://hdlbits.01xz.net/wiki/Gates100
這題跟上題差不多,只是位數變多了。
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
Combinational for-loop: Vector reversal 2⚓︎
Website: https://hdlbits.01xz.net/wiki/Vector100r
這題教程推薦用always block來實作reversal,就可以不用寫generate了。
module top_module(
input [99:0] in,
output [99:0] out
);
integer i;
always@(*)begin
for(i=0;i<100;i++)begin
out[i] = in[99-i];
end
end
endmodule
Combinational for-loop: 255-bit population count⚓︎
Website: https://hdlbits.01xz.net/wiki/Popcount255
這題要算陣列中元素的數量,可以用for loop來實現,然後記得out要初始化為0。
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always@(*)begin
out = 8'b00000000;
for(i=0;i<255;i++)begin
out = out + in[i];
end
end
endmodule
Generate for-loop: 100-bit binary adder 2⚓︎
Website: https://hdlbits.01xz.net/wiki/Adder100i
這題在練習100bit的加法,因為題目要求用module實作1bit full adder,所以這裡只能用generate初始化。
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
full_adder fa_first(.a(a[0]),.b(b[0]),.cin(cin),.cout(cout[0]),.sum(sum[0]));
genvar i;
generate
for(i=1;i<100;i++)begin: block_name
full_adder fa(.a(a[i]),.b(b[i]),.cin(cout[i-1]),.cout(cout[i]),.sum(sum[i]));
end
endgenerate
endmodule
module full_adder(input a,input b,input cin,output cout,output sum);
assign {cout,sum} = a + b + cin;
endmodule
Generate for-loop: 100-digit BCD adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Bcdadd100
這題跟上題差不多,只是將adder變成了BCD-adder。
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [99:0]w;
assign cout = w[99];
bcd_fadd bcd_fadd_first(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(w[0]),.sum(sum[3:0]));
genvar i;
generate
for(i=1;i<100;i++)begin:block_bcd
bcd_fadd bf(.a(a[4*i+3:4*i]),.b(b[4*i+3:4*i]),.cin(w[i-1]),.cout(w[i]),.sum(sum[4*i+3:4*i]));
end
endgenerate
endmodule
Circuits⚓︎
Combinational Logic⚓︎
Basic Gates⚓︎
Wire⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4h
這題就單純接線。
GND⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4i
這題就單純接線。
NOR⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4e
這題就單純接線。
Another gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4f
這題就單純接線。
Two gates⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4g
這題就單純接線。
module top_module (
input in1,
input in2,
input in3,
output out);
assign out = (~(in1 ^ in2))^ in3;
endmodule
More logic gates⚓︎
Website: https://hdlbits.01xz.net/wiki/Gates
這題考各種gate的運算。
module top_module(
input a, b,
output out_and,
output out_or,
output out_xor,
output out_nand,
output out_nor,
output out_xnor,
output out_anotb
);
assign out_and = a & b;
assign out_or = a | b;
assign out_xor = a ^ b;
assign out_nand = ~(a & b);
assign out_nor = ~(a | b);
assign out_xnor = ~(a ^ b);
assign out_anotb = a & (~b);
endmodule
7420 chip⚓︎
Website: https://hdlbits.01xz.net/wiki/7420
這題考稍微複雜的接線。
module top_module (
input p1a, p1b, p1c, p1d,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
assign p1y = ~(p1a & p1b & p1c & p1d);
assign p2y = ~(p2a & p2b & p2c & p2d);
endmodule
Truth tables⚓︎
Website: https://hdlbits.01xz.net/wiki/Truthtable1
這題給了真值表,可以進一步使用卡諾圖化簡。
module top_module(
input x3,
input x2,
input x1, // three inputs
output f // one output
);
assign f = (x3 & x1) | ((~x3) & x2);
endmodule
Two-bit equality⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_eq2
這題用三元運算子就能解決。
module top_module ( input [1:0] A, input [1:0] B, output z );
assign z = (A == B)? 1'b1: 1'b0;
endmodule
Simple circuit A⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_q4a
這題照題目assign就行,如果從類比層面來看,not gate會比and,or,xor還小,強烈推薦多化簡成not gate。
Simple circuit B⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_q4b
這題透過觀察波形,寫出組合邏輯。
Combine circuits A and B⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_q4
這題只是將上兩題當作當作submodule後接線。
module top_module (input x, input y, output z);
wire wa1,wa2,wb1,wb2;
A IA1(.x(x), .y(y), .z(wa1));
A IA2(.x(x), .y(y), .z(wa2));
B IB1(.x(x), .y(y), .z(wb1));
B IB2(.x(x), .y(y), .z(wb2));
assign z = ( wa1 | wb1 ) ^ ( wa2 & wb2 );
endmodule
module A (input x, input y, output z);
assign z = x & (~y);
endmodule
module B ( input x, input y, output z );
assign z = ~(x ^ y);
endmodule
Ring or vibrate?⚓︎
Website: https://hdlbits.01xz.net/wiki/Ringer
這題題目要求用gate寫出符合敘述的邏輯。
module top_module (
input ring,
input vibrate_mode,
output ringer, // Make sound
output motor // Vibrate
);
assign motor = ring & vibrate_mode;
assign ringer = ring & (~vibrate_mode);
endmodule
Thermostat⚓︎
Website: https://hdlbits.01xz.net/wiki/Thermostat
這題跟上題差不多,就是照著條件接出對應的電路。
module top_module (
input too_cold,
input too_hot,
input mode,
input fan_on,
output heater,
output aircon,
output fan
);
assign heater = mode & too_cold;
assign aircon = (~mode) & too_hot;
assign fan = heater | aircon | fan_on;
endmodule
3-bit population count⚓︎
Website: https://hdlbits.01xz.net/wiki/Popcount3
這題就是寫個全加器。
module top_module(
input [2:0] in,
output [1:0] out );
assign out = in[2] + in[1] + in[0];
endmodule
Gates and vectors⚓︎
Website: https://hdlbits.01xz.net/wiki/Gatesv
這題就是練習assign一排運算。
module top_module(
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different );
assign out_both = in[2:0] & in[3:1];
assign out_any = in[2:0] | in[3:1];
assign out_different = in [3:0] ^ {in[0],in[3:1]};
endmodule
Even longer vectors⚓︎
Website: https://hdlbits.01xz.net/wiki/Gatesv100
這題跟上題差不多,只是input vector變長了。
module top_module(
input [99:0] in,
output [98:0] out_both,
output [99:1] out_any,
output [99:0] out_different );
assign out_both = in[98:0] & in[99:1];
assign out_any = in[98:0] | in[99:1];
assign out_different = in [99:0] ^ {in[0],in[99:1]};
endmodule
Multiplexers⚓︎
2-to-1 multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Mux2to1
用三元運算子就能輕鬆寫出multiplexer。
2-to-1 bus multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Mux2to1v
跟上題差不多,用三元運算子就能輕鬆寫出vector的multiplexer。
module top_module(
input [99:0] a, b,
input sel,
output [99:0] out );
assign out = sel ? b : a;
endmodule
9-to-1 multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Mux9to1v
這題可以用case來實現9-to-1 multiplexer。
module top_module(
input [15:0] a, b, c, d, e, f, g, h, i,
input [3:0] sel,
output [15:0] out );
always@(*)begin
case(sel)
4'b0000: out = a;
4'b0001: out = b;
4'b0010: out = c;
4'b0011: out = d;
4'b0100: out = e;
4'b0101: out = f;
4'b0110: out = g;
4'b0111: out = h;
4'b1000: out = i;
default: out = {16{1'b1}};
endcase
end
endmodule
256-to-1 multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Mux256to1
這題講述sel也可以放在index的位置。
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
assign out = in[sel];
endmodule
256-to-1 4-bit multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Mux256to1v
題目講說assign out = in[4*sel+3 :4*sel];
會編不過,所以可以改寫成assign out = in[4*sel +:4];
,從4*sel的地方往上取4位。
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = in[4*sel +:4];
endmodule
Arithmetic Circuits⚓︎
Half adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Hadd
這題就是寫一個半加器。
module top_module(
input a, b,
output cout, sum );
assign cout = a & b;
assign sum = a ^ b;
endmodule
Full adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Fadd
這題就是寫一個全加器。
module top_module(
input a, b, cin,
output cout, sum );
assign {cout,sum} = a + b + cin;
endmodule
3-bit binary adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Adder3
這題就是將3個全加器串在一起。
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
FA FA1(.a(a[0]),.b(b[0]),.cin(cin),.cout(cout[0]),.sum(sum[0]));
FA FA2(.a(a[1]),.b(b[1]),.cin(cout[0]),.cout(cout[1]),.sum(sum[1]));
FA FA3(.a(a[2]),.b(b[2]),.cin(cout[1]),.cout(cout[2]),.sum(sum[2]));
endmodule
module FA(
input a, b, cin,
output cout, sum );
assign {cout,sum} = a + b + cin;
endmodule
Adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4j
這題就是將4個全加器串在一起,順便練習用generate block寫了for loop。
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire [4:1]cout;
assign sum[4] = cout[4];
FA FAA(.a(x[0]),.b(y[0]),.cin(1'b0),.cout(cout[1]),.sum(sum[0]));
genvar i;
generate
for(i=1;i<4;i++)begin:block
FA FAA(.a(x[i]),.b(y[i]),.cin(cout[i]),.cout(cout[i+1]),.sum(sum[i]));
end
endgenerate
endmodule
module FA(
input a, b, cin,
output cout, sum );
assign {cout,sum} = a + b + cin;
endmodule
Signed addition overflow⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q1c
這題單純練習overflow的判別,也就是兩正數相加或兩負數相減時,分別得到負數和正數,那就是發生overflow。
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);
assign s = a + b;
assign overflow = (a[7]&b[7]&(~s[7])) | ((~a[7])&(~b[7])&s[7]);
endmodule
100-bit binary adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Adder100
這題在練習如何用behavioural code描述電路。
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum} = a + b + cin;
endmodule
4-digit BCD adder⚓︎
Website: https://hdlbits.01xz.net/wiki/Bcdadd4
這題在練習串接BCD adder。
module top_module (
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire [3:0] co;
bcd_fadd bf1(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(co[0]),.sum(sum[3:0]));
bcd_fadd bf2(.a(a[7:4]),.b(b[7:4]),.cin(co[0]),.cout(co[1]),.sum(sum[7:4]));
bcd_fadd bf3(.a(a[11:8]),.b(b[11:8]),.cin(co[1]),.cout(co[2]),.sum(sum[11:8]));
bcd_fadd bf4(.a(a[15:12]),.b(b[15:12]),.cin(co[2]),.cout(co[3]),.sum(sum[15:12]));
assign cout = co[3];
endmodule
Karnaugh Map to Circuit⚓︎
3-variable⚓︎
Website: https://hdlbits.01xz.net/wiki/Kmap1
這題練習如何化簡k-map。
module top_module(
input a,
input b,
input c,
output out );
assign out = a | b | c;
endmodule
4-variable(1)⚓︎
Website: https://hdlbits.01xz.net/wiki/Kmap2
這題練習如何化簡k-map,值得注意的是,k map畫圈要重疊,才不會發生hazard。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = (~a & ~d) | (~b & ~c) | (a & ~b & d) | (a & c & d) | (b & c & d);
endmodule
4-variable(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Kmap3
這題練習如何化簡k-map,don't care的部分可以既看成0或看成1化簡,就看方便化簡。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = a | (~b & c);
endmodule
4-variable(3)⚓︎
Website: https://hdlbits.01xz.net/wiki/Kmap4
這題練習如何化簡k-map,有點腦筋急轉彎,這題反而不能想用sum of product或product of sum。
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = a ^ b ^ c ^ d;
endmodule
Minimum SOP and POS⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q2
這題練習如何畫k map並化簡。
module top_module (
input a,
input b,
input c,
input d,
output out_sop,
output out_pos
);
//K map
//cd\ab 00 01 11 10
// 00 0 0 d d
// 01 0 0 0 0
// 11 d 1 1 d
// 10 1 0 0 0
assign out_sop = (c & d) | (~a & ~b & c);
assign out_pos = c & (~a | b) & (~b | d);
endmodule
Karnaugh map(1)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q3
這題練習如何畫k map並化簡。
module top_module (
input [4:1] x,
output f );
assign f = (~x[1] & x[3]) | (x[2] & x[4]);
endmodule
Karnaugh map(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2012_q1g
這題練習如何畫k map並化簡。
module top_module (
input [4:1] x,
output f
);
assign f = (~x[2] & ~x[4])|(~x[1] & x[3])|(x[2] & x[3] & x[4]);
endmodule
K-map implemented with a multiplexer⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q3
這題練習如何畫k map並化簡,比較有意思的是,這題用到了multiplexer畫k-map。
module top_module (
input c,
input d,
output [3:0] mux_in
);
assign mux_in[0] = c | d;
assign mux_in[1] = 1'b0;
assign mux_in[2] = ~d;
assign mux_in[3] = c & d;
endmodule
Sequential Logic⚓︎
Latches and Flip-Flops⚓︎
D flip-flop⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff
這題單純練習如何用sequential block建立DFF,注意要用non-blocking assignment。
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q );//
// Use a clocked always block
// copy d to q at every positive edge of clk
// Clocked always blocks should use non-blocking assignments
always@(posedge clk)
q <= d;
endmodule
D flip-flops⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff8
這題單純練習如何用sequential block建立8-bit input DFF。
module top_module (
input clk,
input [7:0] d,
output reg [7:0] q
);
always@(posedge clk)
q <= d;
endmodule
DFF with reset⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff8r
這題單純練習如何用sequential block建立8-bit input with DFF synchronous reset。
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output reg [7:0] q
);
always@(posedge clk)begin
if(reset) q <= 8'b0000_0000;
else q <= d;
end
endmodule
DFF with reset value⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff8p
這題練習負緣更新,然後題目所說在reset時要更新成0x34,0x的意思是16進位制。
module top_module (
input clk,
input reset,
input [7:0] d,
output reg [7:0] q
);
always@(negedge clk)begin
if(reset) q <= 8'h34;
else q <= d;
end
endmodule
DFF with asynchronous reset⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff8ar
這題要做異步復位的DFF。
module top_module (
input clk,
input areset, // active high asynchronous reset
input [7:0] d,
output reg [7:0] q
);
always@(posedge clk, posedge areset)begin
if(areset) q <= 8'b0000_0000;
else q <= d;
end
endmodule
DFF with byte enable⚓︎
Website: https://hdlbits.01xz.net/wiki/Dff16e
這題就是DFF加上enable。
module top_module (
input clk,
input resetn,
input [1:0] byteena,
input [15:0] d,
output reg[15:0] q
);
always@(posedge clk)begin
if(~resetn) q <= 16'h0000;
else begin
q[15:8] <= byteena[1] ? d[15:8]: q[15:8];
q[7:0] <= byteena[0] ? d[7:0]: q[7:0];
end
end
endmodule
D Latch⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4a
這題練習寫d latch,因為d latch是level-sensitive,所以要用always@(*)
,而因為是sequential logic,所以要用non-blocking assignment。
module top_module (
input d,
input ena,
output reg q);
always@(*)begin
if(ena) q <= d;
end
endmodule
DFF(1)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4b
這題練習寫DFF with asynchronous reset。
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output reg q);
always@(posedge clk,posedge ar)begin
if(ar) q <= 1'b0;
else q <= d;
end
endmodule
DFF(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4c
這題練習寫DFF with synchronous reset,跟上題不同的是,不用考慮reset的正緣觸發。
module top_module (
input clk,
input d,
input r, // synchronous reset
output reg q);
always@(posedge clk)begin
if(r) q <= 1'b0;
else q <= d;
end
endmodule
DFF+gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4d
這題練習寫DFF加上gate的填寫。
module top_module (
input clk,
input in,
output reg out);
always@(posedge clk)begin
out <= out ^ in;
end
endmodule
Mux and DFF(1)⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_muxdff
這題練習一個DFF加上一個mux。
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
always@(posedge clk)begin
Q <= L ? r_in : q_in;
end
endmodule
Mux and DFF(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2014_q4a
這題練習一個DFF加上超過1個gate,此時就可以考慮將combinational logic另外在sequential block外assign好。
module top_module (
input clk,
input w, R, E, L,
output reg Q
);
wire q_in;
assign q_in = L ? R : (E ? w : Q);
always@(posedge clk)begin
Q <= q_in;
end
endmodule
DFFs and gates⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q4
這題只是寫3個DFF。
module top_module (
input clk,
input x,
output z
);
reg q1,q2,q3;
assign z = ~(q1 | q2 | q3);
always@(posedge clk)begin
q1 <= q1 ^ x;
q2 <= ~q2 & x;
q3 <= ~q3 | x;
end
endmodule
Create circuit from truth table⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q7
這題練習寫JK-FF。
module top_module (
input clk,
input j,
input k,
output reg Q);
always @(posedge clk)begin
case({j,k})
2'b00: Q <= Q;
2'b01: Q <= 1'b0;
2'b10: Q <= 1'b1;
2'b11: Q <= ~Q;
endcase
end
endmodule
Detect an edge⚓︎
Website: https://hdlbits.01xz.net/wiki/Edgedetect
這題練習寫edge detection,為了比較上個clk的輸入,要多開一個dff存。
module top_module (
input clk,
input [7:0] in,
output reg [7:0] pedge
);
reg [7:0] in_prev;
always@(posedge clk)begin
in_prev <= in;
pedge <= ~in_prev & in;
end
endmodule
Detect both edges⚓︎
Website: https://hdlbits.01xz.net/wiki/Edgedetect2
這題練習寫edge detection,跟上題不同的是,要同時判斷0變1和1變0。
module top_module (
input clk,
input [7:0] in,
output reg [7:0] anyedge
);
reg [7:0] in_prev;
always@(posedge clk)begin
in_prev <= in;
anyedge <= in ^ in_prev;
end
endmodule
Edge capture register⚓︎
Website: https://hdlbits.01xz.net/wiki/Edgecapture
這題最難的地方就是將edge detection變成edge capture,最簡單的做法就是多or上回合的output。
module top_module (
input clk,
input reset,
input [31:0] in,
output reg [31:0] out
);
reg [31:0] in_prev;
always@(posedge clk)begin
in_prev <= in;
if(reset)
out <= 32'h0000_0000;
else begin
out <= ~in & in_prev | out;
end
end
endmodule
Dual-edge triggered flip-flop⚓︎
Website: https://hdlbits.01xz.net/wiki/Dualedge
這題我直接查解答,這個電路設計也太酷。
module top_module (
input clk,
input d,
output q
);
// Why does this work?
// After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d.
// After negedge clk, n changes to p^n. Thus q = (p^n) = (p^d^p) = d.
reg r1, r2;
assign q = r1 ^ r2;
always@(posedge clk) r1 <= r2 ^ d;
always@(negedge clk) r2 <= r1 ^ d;
endmodule
Counters⚓︎
Four-bit binary counter⚓︎
Website: https://hdlbits.01xz.net/wiki/Count15
這題就是用always來計數。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output reg[3:0] q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else q<= q + 4'b0001;
end
endmodule
Decade counter⚓︎
Website: https://hdlbits.01xz.net/wiki/Count10
這題就是用always來計數,只是數到9,多一個條件。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output reg[3:0] q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else if(q == 4'b1001) q <= 4'b0000;
else q<= q + 4'b0001;
end
endmodule
Decade counter again⚓︎
Website: https://hdlbits.01xz.net/wiki/Count1to10
這題就是用always來計數,只是變成從1數到10。
module top_module (
input clk,
input reset,
output reg[3:0] q);
always@(posedge clk)begin
if(reset) q <=4'b0001;
else if(q == 4'b1010) q<=4'b0001;
else q <= q + 4'b0001;
end
endmodule
Slow decade counter⚓︎
Website: https://hdlbits.01xz.net/wiki/Countslow
這題跟上題差不多,只是變成用另一個輸入計數。
module top_module (
input clk,
input slowena,
input reset,
output reg[3:0] q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else if(slowena)begin
if(q == 4'b1001) q<= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
Counter 1-12⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q7a
這題給了完整的計數器,然後要求外接控制reset和數到12。
module top_module (
input clk,
input reset,
input enable,
output [3:0] Q,
output c_enable,
output c_load,
output [3:0] c_d
); //
assign c_enable = enable;
assign c_load = reset | (enable & (Q == 4'b1100));
assign c_d = 4'b0001;
count4 the_counter (clk, c_enable, c_load, c_d ,Q);
endmodule
Counter 1000⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q7b
這題給了BCD counter,然後要連續接3個BCD counter數到1000。
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
); //
wire [3:0] one, ten, hundred;
wire is_ten, is_hundred;
assign is_ten = (one == 4'b1001);
assign is_hundred = is_ten & (ten == 4'b1001);
assign c_enable = {is_hundred,is_ten,1'b1};
assign OneHertz = is_hundred & (hundred == 4'b1001);
bcdcount counter0 (clk, reset, c_enable[0], one);
bcdcount counter1 (clk, reset, c_enable[1], ten);
bcdcount counter2 (clk, reset, c_enable[2], hundred);
endmodule
4-digit decimal counter⚓︎
Website: https://hdlbits.01xz.net/wiki/Countbcd
這題要自己刻一個BCD,然後要將4個BCD相接,數到9999。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
wire is_ten , is_hundred, is_thousand;
assign is_ten = (q[3:0] == 4'b1001);
assign is_hundred = (q[7:4] == 4'b1001) & is_ten;
assign is_thousand = (q[11:8] == 4'b1001) & is_hundred & is_ten;
assign ena = {is_thousand, is_hundred, is_ten};
BCD BCD0(.clk(clk),.reset(reset),.enable( 1'b1 ),.q(q[3:0]));
BCD BCD1(.clk(clk),.reset(reset),.enable(ena[1]),.q(q[7:4]));
BCD BCD2(.clk(clk),.reset(reset),.enable(ena[2]),.q(q[11:8]));
BCD BCD3(.clk(clk),.reset(reset),.enable(ena[3]),.q(q[15:12]));
endmodule
module BCD(
input clk,
input reset,
input enable,
output reg [4:0] q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else if(enable)begin
if(q == 4'b1001) q <= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
12-hour clock⚓︎
Website: https://hdlbits.01xz.net/wiki/Count_clock
這題刻一個時鐘,算是目前刷題第一次要寫很多程式。
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire enas2,enam1,enam2,enah1,enah2,enapm,ld;
BCD_zero_to_nine s1( .clk(clk), .reset(reset), .enable(ena), .q(ss[3:0]));
assign enas2 = ena & (ss[3:0] == 4'b1001);
BCD_zero_to_six s2( .clk(clk), .reset(reset), .enable(enas2), .q(ss[7:4]));
assign enam1 = enas2 & (ss[7:4] == 4'b0101);
BCD_zero_to_nine m1( .clk(clk), .reset(reset), .enable(enam1), .q(mm[3:0]));
assign enam2 = enam1 & (mm[3:0] == 4'b1001);
BCD_zero_to_six m2( .clk(clk), .reset(reset), .enable(enam2), .q(mm[7:4]));
assign enah1 = enam2 & (mm[7:4] == 4'b0101);
assign ld = enah1 & (hh == 8'b0001_0010);
BCD_zero_to_nine_wload h1( .clk(clk), .reset(reset), .enable(enah1), .load(ld), .q(hh[3:0]));
assign enah2 = (enah1 & (hh[3:0] == 4'b1001)) | ld;
BCD_zero_to_one_wload h2( .clk(clk), .reset(reset), .enable(enah2), .load(ld), .q(hh[7:4]));
assign enapm = enah1 & (hh == 8'b0001_0001);
PM is_pm( .clk(clk), .reset(reset), .enable(enapm), .pm(pm));
endmodule
module BCD_zero_to_nine(
input clk,
input reset,
input enable,
output reg [3:0]q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else if(enable)begin
if(q == 4'b1001) q <= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
module BCD_zero_to_six(
input clk,
input reset,
input enable,
output reg [3:0]q);
always@(posedge clk)begin
if(reset) q <= 4'b0000;
else if(enable)begin
if(q == 4'b0101) q <= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
module BCD_zero_to_nine_wload(
input clk,
input reset,
input enable,
input load,
output reg [3:0]q);
always@(posedge clk)begin
if(reset) q <= 4'b0010;
else if(enable)begin
if(load) q <= 4'b0001;
else if(q == 4'b1001) q <= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
module BCD_zero_to_one_wload(
input clk,
input reset,
input enable,
input load,
output reg [3:0]q);
always@(posedge clk)begin
if(reset) q <= 4'b0001;
else if(enable)begin
if(load) q <= 4'b0000;
else q <= q + 4'b0001;
end
else q <= q;
end
endmodule
module PM(
input clk,
input reset,
input enable,
output reg pm);
always@(posedge clk)begin
if(reset) pm <= 1'b0;
else if(enable) pm <= pm ^ 1'b1;
else pm <= pm;
end
endmodule
Shift Registers⚓︎
4-bit shift register⚓︎
Website: https://hdlbits.01xz.net/wiki/Shift4
這題就是寫個shift register,唯一要注意的是load優先級比enable大。
module top_module(
input clk,
input areset, // async active-high reset to zero
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk, posedge areset)begin
if(areset) q <= 4'b0000;
else if(load) q <= data;
else if(ena) q <= q >> 1;
else q <= q;
end
endmodule
Left/right rotator⚓︎
Website: https://hdlbits.01xz.net/wiki/Rotate100
這題就是寫個rotator,可以使用concatenation來實現rotate。
module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
always@(posedge clk)begin
if(load) q <= data;
else begin
case(ena)
2'b00: q <= q;
2'b01: q <= { q[0], q[99:1]};
2'b10: q <= { q[98:0], q[99]};
2'b11: q <= q;
endcase
end
end
endmodule
Left/right arithmetic shift by 1 or 8⚓︎
Website: https://hdlbits.01xz.net/wiki/Shift18
這題實作arithmetic shift,需注意的是arithmetic shift往右位移時,高位要用補數補位。
module top_module(
input clk,
input load,
input ena,
input [1:0] amount,
input [63:0] data,
output reg [63:0] q);
always@(posedge clk)begin
if(load) q <= data;
else if(ena)begin
case(amount)
2'b00: q <= {q[62:0], 1'b0};
2'b01: q <= {q[55:0],8'b0000_0000};
2'b10: q <= {q[63],q[63:1]};
2'b11: q <= {{8{q[63]}},q[63:8]};
endcase
end
else q <= q;
end
endmodule
5-bit LFSR⚓︎
Website: https://hdlbits.01xz.net/wiki/Lfsr5
這題實作LFSR。
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5'h1
output reg [4:0] q
);
always@(posedge clk)begin
if(reset) q <= 5'b00001;
else q <= {q[0],q[4],q[3] ^ q[0],q[2:1]};
end
endmodule
3-bit LFSR⚓︎
Website: https://hdlbits.01xz.net/wiki/Mt2015_lfsr
這題跟上題一樣實作LFSR。
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [2:0] LEDR); // Q
always@(posedge KEY[0])begin
LEDR <= KEY[1] ? SW: {LEDR[1]^LEDR[2],LEDR[0],LEDR[2]};
end
endmodule
32-bit LFSR⚓︎
Website: https://hdlbits.01xz.net/wiki/Lfsr32
這題還是實作LFSR,taps的意思是指在對應的output放上xor q[0]
,像說taps at 1意思就是q[1] ^ q[0]
。
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32'h1
output reg [31:0] q
);
always@(posedge clk)begin
if(reset) q <= 32'h1;
else q <= {q[0],q[31:23],q[22]^q[0],q[21:3],q[2]^q[0],q[1]^q[0]};
end
endmodule
Shift register(1)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4k
這題單純練習pipeline怎麼切,總之就是多開幾個reg。
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output reg out);
reg q1, q2, q3;
always@(posedge clk)begin
if(~resetn) {q1,q2,q3,out} <= 4'b0000;
else {q1,q2,q3,out} <= {in,q1,q2,q3};
end
endmodule
Shift register(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2014_q4b
這題單純練習寫一個module,然後接成pipeline。
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
MUXDFF ff0( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[1]), .R(SW[0]), .q(LEDR[0]));
MUXDFF ff1( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[2]), .R(SW[1]), .q(LEDR[1]));
MUXDFF ff2( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[3]), .R(SW[2]), .q(LEDR[2]));
MUXDFF ff3( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(KEY[3]), .R(SW[3]), .q(LEDR[3]));
endmodule
module MUXDFF (
input E,
input clk,
input L,
input w,
input R,
output q);
always@(posedge clk)begin
case({L,E})
2'b00: q <= q;
2'b01: q <= w;
default: q <= R;
endcase
end
endmodule
3-input LUT⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q12
這題單純練習寫一個shift register和multiplexer。
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output reg Z );
reg [7:0] Q;
always@(posedge clk)begin
if(enable) Q <= {Q[6:0],S};
else Q <= Q;
end
assign Z = Q[{A,B,C}];
endmodule
More Circuits⚓︎
Rule 90⚓︎
Website: https://hdlbits.01xz.net/wiki/Rule90
這題單純練習concatenation的使用。
module top_module(
input clk,
input load,
input [511:0] data,
output reg [511:0] q );
always @(posedge clk)begin
if(load) q <= data;
else q <= {1'b0,q[511:1]} ^ {q[510:0],1'b0};
end
endmodule
Rule 110⚓︎
Website: https://hdlbits.01xz.net/wiki/Rule110
這題單純練習concatenation的使用,跟上題不同的是,這題有點卡諾圖化簡的感覺。
module top_module(
input clk,
input load,
input [511:0] data,
output reg [511:0] q
);
always@(posedge clk)begin
if(load) q <= data;
else q <= (q ^ {q[510:0],1'b0}) | (~{1'b0,q[511:1]} & q);
end
endmodule
Conway's Game of Life 16x16⚓︎
Website: https://hdlbits.01xz.net/wiki/Conwaylife
這題練習使用for迴圈,還有debug的耐心。
module top_module(
input clk,
input load,
input [255:0] data,
output reg [255:0] q );
reg [255:0] next_q;
reg [323:0] q_padding;
reg [3:0] answer[255:0];
integer i,j;
always@(*)begin
//update q_padding
q_padding[17:0] = {q[240],q[255:240],q[255]};
q_padding[323:306] = {q[0],q[15:0],q[15]};
for(i = 1; i < 17 ; i++)begin
q_padding[i*18 +: 18] = {q[(i-1)*16],q[(i-1)*16 +: 16],q[i*16-1]};
end
//calculate
for(i=0; i<16; i++)begin
for(j=0; j<16; j++)begin
//center is q_padding[18*(i+1)+(j+1)]
answer[16*i + j] = q_padding[18*i+(j )] +
q_padding[18*i+(j+1)] +
q_padding[18*i+(j+2)] +
q_padding[18*(i+1)+(j )] +
q_padding[18*(i+1)+(j+2)] +
q_padding[18*(i+2)+(j )] +
q_padding[18*(i+2)+(j+1)] +
q_padding[18*(i+2)+(j+2)];
case(answer[16*i + j])
4'b0011: next_q[16*i+j] = 1'b1;
4'b0010: next_q[16*i+j] = q[16*i+j];
default: next_q[16*i+j] = 1'b0;
endcase
end
end
end
always@(posedge clk)begin
if(load) q <= data;
else q <= next_q;
end
endmodule
Finite State Machines⚓︎
Simple FSM 1 (asynchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm1
這題寫個FSM,可以進一步化簡。
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output out);//
parameter A=0, B=1;
reg state;
always @(posedge clk, posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(areset) state <= B;
else begin
state <= ~(state ^ in);
end
end
// Output logic
assign out = state;
endmodule
Simple FSM 1 (synchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm1s
這題寫個FSM,跟上一題只差在Synchronous reset,這題練習正常寫FSM。
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
input clk;
input reset; // Synchronous reset to state B
input in;
output out;
// Fill in state name declarations
reg present_state, next_state;
always@(*)begin
case(present_state)
1'b0: next_state = in? 1'b0: 1'b1;
1'b1: next_state = in? 1'b1: 1'b0;
endcase
end
always @(posedge clk) begin
if (reset)present_state <= 1'b1;
else present_state <= next_state;
end
assign out = present_state;
endmodule
Simple FSM 2 (asynchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm2
這題寫個FSM,跟上上一題只差在邏輯有點差異。
module top_module(
input clk,
input areset, // Asynchronous reset to OFF
input j,
input k,
output out); //
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
1'b1: next_state = k? 1'b0: 1'b1;
1'b0: next_state = j? 1'b1: 1'b0;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset) state <= 1'b0;
else state <= next_state;
end
// Output logic
assign out = state;
endmodule
Simple FSM 2 (synchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm2s
這題寫個FSM,跟上一題只差在Synchronous reset,這題練習正常寫FSM。
module top_module(
input clk,
input reset, // Synchronous reset to OFF
input j,
input k,
output out); //
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
1'b1: next_state = k? 1'b0: 1'b1;
1'b0: next_state = j? 1'b1: 1'b0;
endcase
end
always @(posedge clk) begin
// State flip-flops with synchronous reset
if(reset) state <= 1'b0;
else state <= next_state;
end
// Output logic
assign out = state;
endmodule
Simple state transitions 3⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm3comb
這題寫個FSM,只是不需要處理clock。
module top_module(
input in,
input [1:0] state,
output [1:0] next_state,
output out); //
//parameter A=0, B=1, C=2, D=3;
// State transition logic: next_state = f(state, in)
always@(*)begin
case(state)
2'b00: next_state = in? 2'b01: 2'b00;
2'b01: next_state = in? 2'b01: 2'b10;
2'b10: next_state = in? 2'b11: 2'b00;
2'b11: next_state = in? 2'b01: 2'b10;
endcase
end
// Output logic: out = f(state) for a Moore state machine
assign out = &state;
endmodule
Simple one-hot state transitions 3⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm3onehot
這題state是one-hot vector,要求transition table用assign寫,滿特別的。
module top_module(
input in,
input [3:0] state,
output [3:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: Derive an equation for each state flip-flop.
assign next_state[A] = ~in & (state[0] | state[2]);
assign next_state[B] = in & (state[0] | state[1] | state[3]);
assign next_state[C] = ~in & (state[1] | state[3]);
assign next_state[D] = in & (state[2]);
// Output logic:
assign out = state[3];
endmodule
Simple FSM 3 (asynchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm3
這題寫FSM,照著寫就結束了。
module top_module(
input clk,
input in,
input areset,
output out); //
// State transition logic
reg [1:0] state, next_state;
always@(*)begin
case(state)
2'b00: next_state = in? 2'b01: 2'b00;
2'b01: next_state = in? 2'b01: 2'b10;
2'b10: next_state = in? 2'b11: 2'b00;
2'b11: next_state = in? 2'b01: 2'b10;
endcase
end
// State flip-flops with asynchronous reset
always@(posedge clk, posedge areset)begin
if(areset) state <= 2'b00;
else state <= next_state;
end
// Output logic
assign out = &state;
endmodule
Simple FSM 3 (synchronous reset)⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm3s
這題寫FSM,照著寫就結束了,跟上題相比,就是把改成synchronous reset。
module top_module(
input clk,
input in,
input reset,
output out); //
// State transition logic
reg [1:0] state, next_state;
always@(*)begin
case(state)
2'b00: next_state = in? 2'b01: 2'b00;
2'b01: next_state = in? 2'b01: 2'b10;
2'b10: next_state = in? 2'b11: 2'b00;
2'b11: next_state = in? 2'b01: 2'b10;
endcase
end
// State flip-flops with synchronous reset
always@(posedge clk)begin
if(reset) state <= 2'b00;
else state <= next_state;
end
// Output logic
assign out = &state;
endmodule
Design a Moore FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q4
這題考閱讀,照著題意接FSM。
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
reg [1:0]state, next_state;
assign next_state = {s[2],~(s[3]^s[2])&s[1]};
always@(posedge clk)begin
if(reset) state <= 2'b00;
else state <= next_state;
end
always@(*)begin
case(state)
2'b00: {fr3,fr2,fr1} = 3'b111;
2'b01: {fr3,fr2,fr1} = 3'b011;
2'b10: {fr3,fr2,fr1} = 3'b001;
2'b11: {fr3,fr2,fr1} = 3'b000;
endcase
end
always@(posedge clk)begin
if(reset) dfr <= 1'b1;
else begin
if(state > next_state) dfr <= 1'b1;
else if(state== next_state) dfr <= dfr;
else dfr <= 1'b0;
end
end
endmodule
Lemmings 1⚓︎
Website: https://hdlbits.01xz.net/wiki/Lemmings1
這題透過FSM實作遊戲的原理。
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
// parameter LEFT=1, RIGHT=0, ...
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
1'b0: next_state = bump_right? 1'b1: 1'b0;
1'b1: next_state = bump_left? 1'b0: 1'b1;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset) state <= 1'b1;
else state <= next_state;
end
// Output logic
assign walk_left = state;
assign walk_right = ~state;
endmodule
Lemmings 2⚓︎
Website: https://hdlbits.01xz.net/wiki/Lemmings2
這題是上題的延伸,主要是bump的條件要多寫。
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
//0 right_fall, 1 left_fall, 2 right, 3 left
reg [1:0]state,next_state;
always@(*)begin
if(~ground) next_state = {1'b0,state[0]};
else begin
case(state)
2'b00: next_state = 2'b10;
2'b01: next_state = 2'b11;
2'b10: next_state = bump_right? 2'b11: 2'b10;
2'b11: next_state = bump_left ? 2'b10: 2'b11;
endcase
end
end
always@(posedge clk,posedge areset)begin
if(areset) state <= 2'b11;
else state <= next_state;
end
assign walk_left = &state;
assign walk_right = state[1] & ~state[0];
assign aaah = ~state[1];
endmodule
Lemmings 3⚓︎
Website: https://hdlbits.01xz.net/wiki/Lemmings3
這題是上題的延伸,主要是dig的條件要多寫,然後如果照著fsm格式寫應該會快樂不少。
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
//right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101
reg [2:0] state,next_state;
always@(*)begin
case(state)
3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
3'b010: next_state= ground? 3'b000: 3'b010;
3'b011: next_state= ground? 3'b001: 3'b011;
3'b100: next_state= ground? 3'b100: 3'b010;
3'b101: next_state= ground? 3'b101: 3'b011;
default: next_state= 3'bxxx;
endcase
end
always@(posedge clk,posedge areset)begin
if(areset) state <= 3'b001;
else state <= next_state;
end
assign walk_left = ~state[2] & ~state[1] & state[0];
assign walk_right = &(~state);
assign aaah = ~state[2] & state[1];
assign digging = state[2];
endmodule
Lemmings 4⚓︎
Website: https://hdlbits.01xz.net/wiki/Lemmings4
這題是上題的延伸,也是FSM和counter的結合,這裡只需要注意counter在sequential的logic不要寫錯了,我當時把if(~next_state[2] & next_state[1])
寫成if(~state[2] & state[1])
,一直少算一回合。
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
//right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101,splatter 3'b110
reg [2:0] state,next_state;
reg [7:0] count;
always@(*)begin
case(state)
3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
3'b010: next_state= ground? ((count>8'd20)? 3'b110: 3'b000): 3'b010;
3'b011: next_state= ground? ((count>8'd20)? 3'b110: 3'b001): 3'b011;
3'b100: next_state= ground? 3'b100: 3'b010;
3'b101: next_state= ground? 3'b101: 3'b011;
3'b110: next_state = 3'b110;
default: next_state= 3'bxxx;
endcase
end
always@(posedge clk,posedge areset)begin
if(areset)begin
state <= 3'b001;
count <= 8'd0;
end
else begin
state <= next_state;
if(~next_state[2] & next_state[1])
count <= count + 8'd1;
else
count <= 8'd0;
end
end
assign walk_left = ~state[2] & ~state[1] & state[0];
assign walk_right = &(~state);
assign aaah = ~state[2] & state[1];
assign digging = state[2] & ~state[1];
endmodule
One-hot FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_onehot
這題不用寫DFF,而且又是one hot vector,所以很適合用assign來寫完transition logic。
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
//next state
assign next_state[0] = ~in & (state[0]| state[1]| state[2]| state[3]| state[4]| state[7]| state[8]| state[9]);
assign next_state[1] = in & (state[0]| state[8]| state[9]);
assign next_state[2] = in & state[1];
assign next_state[3] = in & state[2];
assign next_state[4] = in & state[3];
assign next_state[5] = in & state[4];
assign next_state[6] = in & state[5];
assign next_state[7] = in & (state[6]| state[7]);
assign next_state[8] = ~in & state[5];
assign next_state[9] = ~in & state[6];
//out
assign out1 = state[8]| state[9];
assign out2 = state[7]| state[9];
endmodule
PS/2 packet parser⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_ps2
這題有點edge detection的感覺,或許可以開3個reg存前3回合的輸入,不過用FSM可以更理想的省空間。
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
//2'b00 -> reset
//2'b01 -> get the 1xx
//2'b11 -> output done = 1
reg [1:0]state, next_state;
// State transition logic (combinational)
always@(*)begin
case(state)
2'b00: next_state = in[3]? 2'b01: 2'b00;
2'b01: next_state = 2'b10;
2'b10: next_state = 2'b11;
2'b11: next_state = in[3]? 2'b01: 2'b00;
endcase
end
// State flip-flops (sequential)
always@(posedge clk)begin
if(reset) state <= 2'b00;//reset
else state <= next_state;
end
// Output logic
assign done = state[1] & state [0];//done when state== 2'b11
endmodule
PS/2 packet parser and datapath⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_ps2data
這題延續上題,就只是開個datapath來存過往資料。
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
// FSM from fsm_ps2
//2'b00 -> reset
//2'b01 -> get the 1xx
//2'b11 -> output done = 1
reg [1:0]state, next_state;
// State transition logic (combinational)
always@(*)begin
case(state)
2'b00: next_state = in[3]? 2'b01: 2'b00;
2'b01: next_state = 2'b10;
2'b10: next_state = 2'b11;
2'b11: next_state = in[3]? 2'b01: 2'b00;
endcase
end
// State flip-flops (sequential)
always@(posedge clk)begin
if(reset) state <= 2'b00;//reset
else state <= next_state;
end
// Output logic
assign done = state[1] & state [0];//done when state== 2'b11
// New: Datapath to store incoming bytes.
reg [7:0] in1, in2, in3;
always@(posedge clk)begin
in1 <= in;
in2 <= in1;
in3 <= in2;
end
assign out_bytes = done? {in3, in2, in1}: {24{1'b0}};
endmodule
Serial receiver⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_serial
這題單純考怎麼將應用題轉成FSM。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
//data*8 + start + stop + idle + ??? = 12state
reg[3:0] state, next_state;
always@(*)begin
case(state)
4'd0: next_state = in? 4'd0: 4'd1;//idle
4'd1: next_state = 4'd2;//start
4'd2: next_state = 4'd3;//data1
4'd3: next_state = 4'd4;//data2
4'd4: next_state = 4'd5;//data3
4'd5: next_state = 4'd6;//data4
4'd6: next_state = 4'd7;//data5
4'd7: next_state = 4'd8;//data6
4'd8: next_state = 4'd9;//data7
4'd9: next_state = in? 4'd10: 4'd11;//data8
4'd10: next_state = in? 4'd0: 4'd1;//stop
4'd11: next_state = in? 4'd0: 4'd11;//???
default: next_state = 4'bxxxx;
endcase
end
assign done = (state == 4'd10);
always@(posedge clk)begin
if(reset) state <= 4'b0000;
else state <= next_state;
end
endmodule
Serial receiver and datapath⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_serialdata
這題接續上題,多加一個datapath存資料。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Use FSM from Fsm_serial
//data*8 + start + stop + idle + ??? = 12state
reg[3:0] state, next_state;
always@(*)begin
case(state)
4'd0: next_state = in? 4'd0: 4'd1;//idle
4'd1: next_state = 4'd2;//start
4'd2: next_state = 4'd3;//data1
4'd3: next_state = 4'd4;//data2
4'd4: next_state = 4'd5;//data3
4'd5: next_state = 4'd6;//data4
4'd6: next_state = 4'd7;//data5
4'd7: next_state = 4'd8;//data6
4'd8: next_state = 4'd9;//data7
4'd9: next_state = in? 4'd10: 4'd11;//data8
4'd10: next_state = in? 4'd0: 4'd1;//stop
4'd11: next_state = in? 4'd0: 4'd11;//???
default: next_state = 4'bxxxx;
endcase
end
assign done = (state == 4'd10);
always@(posedge clk)begin
if(reset) state <= 4'b0000;
else state <= next_state;
end
// New: Datapath to latch input bits.
reg [8:0] data;
always@(posedge clk)begin
data <= {in,data[8:1]};
end
assign out_byte = data[7:0];
endmodule
Serial receiver with parity checking⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_serialdp
這題接續上題,data input從8 bit變9 bit,所以FSM要改。然後有個細節要注意,就是parity的reset等到start階段時也要reset。至於說如何判別is_start
,這裡得用assign is_start = (next_state == 4'd1);
,不能用assign is_start = (state == 4'd1);
的原因在於,會晚一個cycle。所以把握一個原則,sequential logic中若用到狀態,記得要寫next_state。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Modify FSM and datapath from Fsm_serialdata
// Use FSM from Fsm_serial
//data*8 + start + stop + idle + ??? = 12state
reg[3:0] state, next_state;
always@(*)begin
case(state)
4'd0: next_state = in? 4'd0: 4'd1;//idle
4'd1: next_state = 4'd2;//start
4'd2: next_state = 4'd3;//data1
4'd3: next_state = 4'd4;//data2
4'd4: next_state = 4'd5;//data3
4'd5: next_state = 4'd6;//data4
4'd6: next_state = 4'd7;//data5
4'd7: next_state = 4'd8;//data6
4'd8: next_state = 4'd9;//data7
4'd9: next_state = 4'd10;//data8
4'd10: next_state = in? 4'd11: 4'd12;//data9
4'd11: next_state = in? 4'd0: 4'd1;//stop
4'd12: next_state = in? 4'd0: 4'd12;//???
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= 4'b0000;
else begin
state <= next_state;
valid <= odd;
end
end
// New: Datapath to latch input bits.
reg [9:0] data;
always@(posedge clk)begin
data <= {in,data[9:1]};
end
// New: Add parity checking.
wire odd,is_start;
assign is_start = (next_state == 4'd1);
parity pr(.clk(clk),.reset(reset|is_start),.in(in),.odd(odd));
reg valid;
assign out_byte = valid? data[7:0]: 8'd0;
assign done = (state == 4'd11) & valid;
endmodule
Sequence recognition⚓︎
Website: https://hdlbits.01xz.net/wiki/Fsm_hdlc
這題分別對連續5,6,7以上個1做判斷,並做相對應的輸出,其實很像進階版的edge detection,不過可以用FSM實現,可以少幾個register。
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
reg [3:0] state, next_state;
parameter none = 4'd0;
parameter one = 4'd1;
parameter two = 4'd2;
parameter three = 4'd3;
parameter four = 4'd4;
parameter five = 4'd5;
parameter six = 4'd6;
parameter seven = 4'd7;
parameter discard = 4'd8;
parameter fg = 4'd9;
always@(*)begin
case(state)
none: next_state = in? one: none;
one: next_state = in? two: none;
two: next_state = in? three: none;
three: next_state = in? four: none;
four: next_state = in? five: none;
five: next_state = in? six: discard;
six: next_state = in? seven: fg;
seven: next_state = in? seven: none;
discard: next_state = in? one: none;
fg: next_state = in? one: none;
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= none;
else state <= next_state;
end
assign disc = (state == discard);
assign flag = (state == fg);
assign err = (state == seven);
endmodule
Q8: Design a Mealy FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q8
這題應該是這網站上第一題明確指出需使用mealy machine的題目。
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
reg [1:0] state, next_state;
parameter zero_bit = 2'b00;
parameter one_bit = 2'b01;
parameter two_bit = 2'b10;
always@(*)begin
case(state)
zero_bit: next_state = x? one_bit: zero_bit;
one_bit: next_state = x? one_bit: two_bit;
two_bit: next_state = x? one_bit: zero_bit;
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk, negedge aresetn)begin
if(~aresetn) state <= zero_bit;
else state <= next_state;
end
assign z = (state == two_bit) && x;
endmodule
Q5a: Serial two's complementer (Moore FSM)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5a
這題用moore machine寫2補數,就只有lsb的1輸出改1,沒什麼太難的。
module top_module (
input clk,
input areset,
input x,
output z
);
reg [1:0] state, next_state;
parameter idle = 2'b00;
parameter zero = 2'b01;
parameter one = 2'b10;
always@(*)begin
case(state)
idle: next_state = x? zero: idle;
zero: next_state = x? one: zero;
one: next_state = x? one: zero;
default: next_state = 2'bxx;
endcase
end
always@(posedge clk, posedge areset)begin
if(areset) state <= 2'b00;
else state <= next_state;
end
assign z = (state == zero);
endmodule
Q5b: Serial two's complementer (Mealy FSM)⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5b
這題用mealy machine,因為mealy machine比moore machine少一個state,所以輸出早一個週期。
module top_module (
input clk,
input areset,
input x,
output z
);
reg state, next_state;
parameter idle = 1'b0;
parameter comp = 1'b1;
assign next_state = state | x;
always@(posedge clk,posedge areset)begin
if(areset) state = idle;
else state = next_state;
end
assign z = (state & ~x) | (~state & x);
endmodule
Q3a: FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3fsm
這題在考怎麼算三個cycle內有兩個1,其實可以開個datapath,然後取xnor和or。然後有個細節要注意,就是當reset和A轉換為B時要將datapath更新成3'b000,這裡得寫else if(state == A) temp <= 3'b000;
而不是寫else if(next_state == B) temp <= 3'b000;
的原因在於,next_state == B
也可能代表next_state == D
。
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
reg [1:0] state, next_state;
parameter A = 2'b00;
parameter B = 2'b01;
parameter C = 2'b10;
parameter D = 2'b11;
always@(*)begin
case(state)
A: next_state = s? B: A;
B: next_state = C;
C: next_state = D;
D: next_state = B;
endcase
end
reg [2:0]temp;
always@(posedge clk)begin
if(reset) state <= A;
else state <= next_state;
end
always@(posedge clk)begin
if(reset) temp <= 3'b000;
else if(state == A) temp <= 3'b000;
else temp <= {temp[1:0],w};
end
assign z = (state == B) && ~(^temp) && (|temp);
endmodule
Q3b: FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3bfsm
這題就照table寫Moore Machine,沒什麼難度。
module top_module (
input clk,
input reset, // Synchronous reset
input x,
output z
);
reg [2:0] state, next_state;
always@(*)begin
case(state)
3'b000: next_state = x? 3'b001: 3'b000;
3'b001: next_state = x? 3'b100: 3'b001;
3'b010: next_state = x? 3'b001: 3'b010;
3'b011: next_state = x? 3'b010: 3'b001;
3'b100: next_state = x? 3'b100: 3'b011;
default: next_state = 3'bxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= 3'b000;
else state <= next_state;
end
assign z = (~state[2]& state[1] & state[0]) | (state[2]& ~state[1] & ~state[0]);
endmodule
Q3c: FSM logic⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3c
這題因為有input clk,差點寫矇了,實際上因為這題的y是input給的,所以完全不用使用sequential block,也就用不上clk。
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
reg [2:0] next_state;
always@(*)begin
case(y)
3'b000: next_state = x? 3'b001: 3'b000;
3'b001: next_state = x? 3'b100: 3'b001;
3'b010: next_state = x? 3'b001: 3'b010;
3'b011: next_state = x? 3'b010: 3'b001;
3'b100: next_state = x? 3'b100: 3'b011;
default: next_state = 3'bxxx;
endcase
end
assign Y0 = next_state[0];
assign z = (~y[2]& y[1] & y[0]) | (y[2]& ~y[1] & ~y[0]);
endmodule
Q6b: FSM next-state logic⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6b
這題就照著FSM圖表寫完code就結束了,水題一題。
module top_module (
input [3:1] y,
input w,
output Y2);
parameter A = 3'd0;
parameter B = 3'd1;
parameter C = 3'd2;
parameter D = 3'd3;
parameter E = 3'd4;
parameter F = 3'd5;
reg [3:1]next_state;
always@(*)begin
case(y)
A: next_state = w? A: B;
B: next_state = w? D: C;
C: next_state = w? D: E;
D: next_state = w? A: F;
E: next_state = w? D: E;
F: next_state = w? D: C;
default: next_state = 3'bxxx;
endcase
end
assign Y2 = next_state[2];
endmodule
Q6c: FSM one-hot next-state logic⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6c
這題跟上題很像,不過改成用assign完成,有關one hot vector一律建議使用assign。
module top_module (
input [6:1] y,
input w,
output Y2,
output Y4);
assign Y2 = ~w & y[1];
assign Y4 = w & (y[2] | y[3] | y[5] | y[6]);
endmodule
Q6: FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6
這題就是上上題的完整版,把sequential logic寫完就結束了。
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A = 3'd0;
parameter B = 3'd1;
parameter C = 3'd2;
parameter D = 3'd3;
parameter E = 3'd4;
parameter F = 3'd5;
reg [2:0] state,next_state;
always@(*)begin
case(state)
A: next_state = w? A: B;
B: next_state = w? D: C;
C: next_state = w? D: E;
D: next_state = w? A: F;
E: next_state = w? D: E;
F: next_state = w? D: C;
default: next_state = 3'bxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= A;
else state <= next_state;
end
assign z = state[2] & ~state[1];
endmodule
Q2a: FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2012_q2fsm
這題就是上題把input w complement,所以很容易就寫完。
module top_module (
input clk,
input reset, // Synchronous active-high reset
input w,
output z
);
parameter A = 3'd0;
parameter B = 3'd1;
parameter C = 3'd2;
parameter D = 3'd3;
parameter E = 3'd4;
parameter F = 3'd5;
reg [2:0] state,next_state;
always@(*)begin
case(state)
A: next_state = w? B: A;
B: next_state = w? C: D;
C: next_state = w? E: D;
D: next_state = w? F: A;
E: next_state = w? E: D;
F: next_state = w? C: D;
default: next_state = 3'bxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= A;
else state <= next_state;
end
assign z = state[2] & ~state[1];
endmodule
Q2b: One-hot FSM equations⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2012_q2b
這題就是上上上題把input w complement,所以很容易就寫完。
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
assign Y1 = w & y[0];
assign Y3 = ~w & (y[1] | y[2] | y[4] | y[5]);
endmodule
Q2a: FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2013_q2afsm
這題就是照著圖寫FSM,沒什麼太多的技巧。
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
reg [1:0] state, next_state;
parameter A = 2'b00;
parameter B = 2'b01;
parameter C = 2'b10;
parameter D = 2'b11;
always@(*)begin
case(state)
A:begin
if(~|r) next_state = A;
else if(r[3:1] == 3'b100) next_state = D;
else if(r[2:1] == 2'b10) next_state = C;
else if(r[1]) next_state = B;
else next_state = 2'bxx;
end
B: next_state = r[1]? B: A;
C: next_state = r[2]? C: A;
D: next_state = r[3]? D: A;
endcase
end
always@(posedge clk)begin
if(~resetn) state <= A;
else state <= next_state;
end
assign g = {(state == D), (state == C), (state == B)};
endmodule
Q2b: Another FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/2013_q2bfsm
這題就是照著題目敘述寫FSM,考的是英文能力和debug通靈技巧。
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
reg [3:0]state, next_state;
parameter A = 4'd0;
parameter f_1 = 4'd1;
parameter zero_bit = 4'd2;
parameter one_bit = 4'd3;
parameter two_bit = 4'd4;
parameter three_bit = 4'd5;
parameter g_0 = 4'd6;
parameter g_1 = 4'd7;
parameter temp = 4'd8;
always@(*)begin
case(state)
A: next_state = f_1;
f_1: next_state = zero_bit;
zero_bit: next_state = x? one_bit: zero_bit;
one_bit: next_state = x? one_bit: two_bit;
two_bit: next_state = x? three_bit: zero_bit;
three_bit: next_state = y? g_1: temp;
g_0: next_state = g_0;
temp: next_state = y? g_1: g_0;
g_1: next_state = g_1;
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(~resetn) state <= A;
else state <= next_state;
end
assign f = (state == f_1);
assign g = (state == three_bit) | (state == temp) | (state == g_1);
endmodule
Building Larger Circuits⚓︎
Counter with period 1000⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_count1k
這題只是看起來位數很多很嚇人,如果熟練的話可以寫得很簡潔。
module top_module (
input clk,
input reset,
output reg[9:0] q);
always@(posedge clk)begin
if(reset) q <= 10'd0;
else if(q == 10'd999) q <= 10'd0;
else q <= q + 1'b1;
end
endmodule
4-bit shift register and down counter⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_shiftcount
這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output reg[3:0] q);
always@(posedge clk)begin
case({shift_ena, count_ena})
2'b00: q <= q;
2'b01: q <= q - 1'b1;
2'b10: q <= {q[2:0],data};
2'b11: q <= 4'bxxxx;
endcase
end
endmodule
FSM: Sequence 1101 recognizer⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmseq
這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting);
reg [2:0] state, nstate;
parameter zero = 3'd0;
parameter one = 3'd1;
parameter two = 3'd2;
parameter three = 3'd3;
parameter four = 3'd4;
always@(*)begin
case(state)
zero: nstate = data? one: zero;
one: nstate = data? two: zero;
two: nstate = data? two: three;
three: nstate = data? four: zero;
four: nstate = four;
default: nstate = 3'bxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= zero;
else state <= nstate;
end
assign start_shifting = (state == four);
endmodule
FSM: Enable shift register⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmshift
這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [2:0] counter;
always@(posedge clk)begin
if(reset) counter <= 3'd0;
else if(counter == 3'd4) counter <= counter;
else counter <= counter + 1'b1;
end
assign shift_ena = ~counter[2];
endmodule
FSM: The complete FSM⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsm
這題就是前三題的綜合,如果已經寫過Lemmings4
,應該覺得這題佛心來著。
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output shift_ena,
output counting,
input done_counting,
output done,
input ack );
reg [3:0] state, nstate;
parameter re = 4'd0;
parameter l = 4'd1;
parameter ll = 4'd2;
parameter llo = 4'd3;
parameter llol = 4'd4;
parameter s1 = 4'd5;
parameter s2 = 4'd6;
parameter s3 = 4'd7;
parameter is_counting = 4'd8;
parameter is_done = 4'd9;
always@(*)begin
case(state)
re: nstate = data? l: re;
l: nstate = data? ll: re;
ll: nstate = data? ll: llo;
llo: nstate = data? llol: re;
llol: nstate = s1;
s1: nstate = s2;
s2: nstate = s3;
s3: nstate = is_counting;
is_counting: nstate = done_counting? is_done: is_counting;
is_done: nstate = ack? re: is_done;
default: nstate = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= re;
else state <= nstate;
end
assign shift_ena = (state == s1) | (state == s2) | (state == s3) | (state == llol);
assign counting = (state == is_counting);
assign done = (state == is_done);
endmodule
The complete timer⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fancytimer
這題單純在比耐心和debug能力,順便考驗怎麼省空間,我也覺得delay透過倒數的方式,可能空間可以少不少。
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output [3:0] count,
output counting,
output done,
input ack );
//FSM
reg [3:0] state,next_state;
parameter re = 4'd0;
parameter l = 4'd1;
parameter ll = 4'd2;
parameter llo = 4'd3;
parameter shift_o = 4'd4;
parameter shift_l = 4'd5;
parameter shift_lo = 4'd6;
parameter shift_ll = 4'd7;
parameter is_count = 4'd8;
parameter is_finish = 4'd9;
always@(*)begin
case(state)
re: next_state = data ? l: re;
l: next_state = data? ll: re;
ll: next_state = data? ll: llo;
llo: next_state = data? shift_o: re;
shift_o: next_state = shift_l;
shift_l: next_state = shift_lo;
shift_lo: next_state = shift_ll;
shift_ll: next_state = is_count;
is_count: next_state = ((num == 15'd999)&(data_pipe == 4'd0))? is_finish: is_count;
is_finish: next_state = ack? re: is_finish;
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= re;
else state <= next_state;
end
//Counter
reg [9:0] num;
always@(posedge clk)begin
if(reset) num <= 10'd0;
else if(num == 10'd999) num <= 10'd0;
else if(counting) num <= num +10'd1;
else num <= num;
end
//Data
wire is_data_shift;
reg [3:0] data_pipe;
assign is_data_shift = (state == shift_o) | (state == shift_l) | (state == shift_lo) | (state == shift_ll);
always@(posedge clk)begin
if(reset) data_pipe <= 4'd0;
else if(is_data_shift) data_pipe <= {data_pipe[2:0], data};
else if(num == 10'd999) data_pipe <= data_pipe - 1'b1;
else data_pipe <= data_pipe;
end
assign count = data_pipe;
assign counting = (state == is_count);
assign done = (state == is_finish);
endmodule
FSM: One-hot logic equations⚓︎
Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmonehot
這題跟上題比,不需要考慮clock,要用assign接,滿容易的。
module top_module(
input d,
input done_counting,
input ack,
input [9:0] state, // 10-bit one-hot current state
output B3_next,
output S_next,
output S1_next,
output Count_next,
output Wait_next,
output done,
output counting,
output shift_ena
); //
// You may use these parameters to access state bits using e.g., state[B2] instead of state[6].
parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
assign B3_next = state[B2];
assign S_next = (state[Wait] & ack) | (state[S] & ~d) | (state[S1] & ~d) | (state[S110] & ~d);
assign S1_next = state[S] & d;
assign Count_next = state[B3] | (state[Count] & ~done_counting);
assign Wait_next = (state[Count] & done_counting) | (state[Wait] & ~ack);
assign done = state[Wait];
assign counting = state[Count];
assign shift_ena = state[B0] | state[B1] | state[B2] | state[B3];
endmodule
Verification: Reading Simulations⚓︎
Finding bugs in code⚓︎
Mux⚓︎
Website: https://hdlbits.01xz.net/wiki/Bugs_mux2
終於到了要debug的題型了,這部分相對先前的題型友善許多,這題的bug出在output要改成8bit,還有用三元運算可能方便一點。
module top_module (
input sel,
input [7:0] a,
input [7:0] b,
output [7:0] out );
assign out = sel? a: b;
endmodule
NAND⚓︎
Website: https://hdlbits.01xz.net/wiki/Bugs_nand3
這題要寫nand,所以最後要接個not gate,然後要使用submodule的話,參數要馬照順序給,要馬照名字給。
module top_module (input a, input b, input c, output out);//
wire out_inv;
andgate inst1 ( .out(out_inv), .a(a), .b(b), .c(c), .d(1'b1), .e(1'b1) );
assign out = ~out_inv;
endmodule
Mux(2)⚓︎
Website: https://hdlbits.01xz.net/wiki/Bugs_mux4
這題問題出在wire沒開vector,sel亂接,還有變數重複命名。
module top_module (
input [1:0] sel,
input [7:0] a,
input [7:0] b,
input [7:0] c,
input [7:0] d,
output [7:0] out ); //
wire [7:0]mux0, mux1;
mux2 mux_0 ( sel[0], a, b, mux0 );
mux2 mux_1 ( sel[0], c, d, mux1 );
mux2 mux_2 ( sel[1], mux0, mux1, out );
endmodule
Add/sub⚓︎
Website: https://hdlbits.01xz.net/wiki/Bugs_addsubz
這題問題出在他把logical not和arithmetic not搞混了,還有沒寫else,會產生latch。
// synthesis verilog_input_version verilog_2001
module top_module (
input do_sub,
input [7:0] a,
input [7:0] b,
output reg [7:0] out,
output reg result_is_zero
);//
always @(*) begin
case (do_sub)
0: out = a+b;
1: out = a-b;
endcase
if (!out)
result_is_zero = 1;
else result_is_zero = 0;
end
endmodule
Case statement⚓︎
Website: https://hdlbits.01xz.net/wiki/Bugs_case
這題問題出在他進位亂寫,bit亂寫,改一下就結束了。
module top_module (
input [7:0] code,
output reg [3:0] out,
output reg valid=1'b1 );//
always @(*)
case (code)
8'h45: out = 4'd0;
8'h16: out = 4'd1;
8'h1e: out = 4'd2;
8'h26: out = 4'd3;
8'h25: out = 4'd4;
8'h2e: out = 4'd5;
8'h36: out = 4'd6;
8'h3d: out = 4'd7;
8'h3e: out = 4'd8;
8'h46: out = 4'd9;
default: out = 4'd0;
endcase
always@(*)begin
if(!(code == 8'h45) & !(out))
valid = 1'b0;
else
valid = 1'b1;
end
endmodule
Build a circuit from a simulation waveform⚓︎
Combinational circuit 1⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit1
這系列是看波形寫code,也滿快樂的。
Combinational circuit 2⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit2
這題單純就是觀察有偶數個input時,output是1,所以就是xnor gate。
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = ~(a ^ b ^ c ^ d);
endmodule
Combinational circuit 3⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit3
這題單純就是觀察,當非c且非d,或非a且非b時,輸出為0。反過來說,當c或d,且a或b時,輸出為1。
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = (a | b) & (c | d);
endmodule
Combinational circuit 4⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit4
這題單純就是觀察,當b或c時,輸出為1。
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = b | c; // Fix me
endmodule
Combinational circuit 5⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit5
透過觀察可以知道,當c是0,1,2,3時,對應的輸入為b,e,a,d四個input,否則output 4'hf,或是說是4'b1111。
module top_module (
input [3:0] a,
input [3:0] b,
input [3:0] c,
input [3:0] d,
input [3:0] e,
output reg [3:0] q );
always@(*)begin
case(c)
4'd0: q = b;
4'd1: q = e;
4'd2: q = a;
4'd3: q = d;
default: q = 4'hf;
endcase
end
endmodule
Combinational circuit 6⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit6
透過觀察可以知道,這題有點像是decoder,不過有指定的輸出。
module top_module (
input [2:0] a,
output [15:0] q );
always@(*)begin
case(a)
3'd0: q = 16'h1232;
3'd1: q = 16'haee0;
3'd2: q = 16'h27d4;
3'd3: q = 16'h5a0e;
3'd4: q = 16'h2066;
3'd5: q = 16'h64ce;
3'd6: q = 16'hc526;
3'd7: q = 16'h2f19;
endcase
end
endmodule
Sequential circuit 7⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit7
透過觀察可以知道,這題就是q就是a接了inverter,只不過晚一回合輸出。
module top_module (
input clk,
input a,
output q );
reg state, next_state;
parameter zero_1 = 1'd0;
parameter one_1 = 1'd1;
always@(*)begin
next_state = a? one_1: zero_1;
end
always@(posedge clk)begin
state <= next_state;
end
assign q = ~state;
endmodule
Sequential circuit 8⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit8
q的話很容易看出來是negetive edge的d flip-flop,p的話就是要觀察到是latch結構。
module top_module (
input clock,
input a,
output p,
output reg q );
assign p = clock? a: p;
always@(negedge clock)begin
q <= a;
end
endmodule
Sequential circuit 9⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit9
這題能觀察出是個計時器結構。
module top_module (
input clk,
input a,
output reg[3:0] q );
always@(posedge clk)begin
if(a) q <= 4'd4;
else if(q == 4'd6) q <= 4'd0;
else q <= q + 1'd1;
end
endmodule
Sequential circuit 10⚓︎
Website: https://hdlbits.01xz.net/wiki/Sim/circuit10
這題要想成是一台FSM,然後好好觀察在不同state和input下時,state的輸出。
module top_module (
input clk,
input a,
input b,
output reg q,
output reg state );
reg next_state;
always@(*)begin
case(state)
1'b0: next_state = a & b;
1'b1: next_state = a | b;
endcase
end
always@(posedge clk)begin
state <= next_state;
end
assign q = state ^ a ^ b;
endmodule
Verification: Writing Testbenches⚓︎
Clock⚓︎
Website: https://hdlbits.01xz.net/wiki/Tb/clock
這題是hdlbits第一次讓人練習testbench,所以就講詳細點。
第一行的格式是`timescale 時間單位/時間精度
。
像說下列的程式有講到#5
,代表delay5個時間單位,然後這裡的時間單位就是5ps。
然後時間精度的話,代表說模擬的最小尺度,可以粗略的理解成像是c++的floating point,最小最小只能觀察到的尺度,像程式碼這裡最小尺度就是1ps。
有關timescale的說明,可以多看這個網站: https://www.chipverify.com/verilog/verilog-timescale
然後在testbench中,給submodule的input用reg,接收submodule的output用wire。原因在於,對於submodule來說的input,對testbench來說是output,對於submodule來說的output,對於testbench是input。
然後initial裡面放初始化數值,然後這個題目要無限重複clk,所以不用寫$finish
。
`timescale 1ps/1ps
module top_module ( );
reg clk;
initial begin
clk = 1'b0;
end
always #5 clk = ~clk;
dut inst( .clk(clk)) ;
endmodule
Testbench1⚓︎
Website: https://hdlbits.01xz.net/wiki/Tb/tb1
這題不像上題要一直無限clk,可以透過$finish
來限制模擬時間。
module top_module ( output reg A, output reg B );//
// generate input patterns here
initial begin
A = 1'b0;
B = 1'b0;
#10 A = 1'b1;
#5 B = 1'b1;
#5 A = 1'b0;
#20 B = 1'b0;
#300 $finish;
end
endmodule
AND gate⚓︎
Website: https://hdlbits.01xz.net/wiki/Tb/and
這題不像上題要一直無限clk,可以透過$finish
來限制模擬時間。
module top_module();
reg [1:0]in;
wire out;
initial begin
in = 2'b00;
#10 in = 2'b01;
#10 in = 2'b10;
#10 in = 2'b11;
#20 $finish;
end
andgate and_gate(.in(in), .out(out));
endmodule
Testbench2⚓︎
Website: https://hdlbits.01xz.net/wiki/Tb/tb2
這題reg和wire變多了,可以考慮把initial block分開寫,可讀性較佳。
module top_module();
reg clk, in;
reg [2:0] s;
wire out;
initial begin
clk = 1'b0;
end
always #5 clk = ~clk;
initial begin
in = 1'b0;
#20 in = 1'b1;
#10 in = 1'b0;
#10 in = 1'b1;
#30 in = 1'b0;
end
initial begin
s = 3'd2;
#10 s = 3'd6;
#10 s = 3'd2;
#10 s = 3'd7;
#10 s = 3'd0;
end
initial begin
#100 $finish;
end
q7 inst(.clk(clk), .in(in), .s(s), .out(out));
endmodule
T flip-flop⚓︎
Website: https://hdlbits.01xz.net/wiki/Tb/tff
這題照著題目要求寫,就結束了。完全不用考慮時間間隔弄多少。
module top_module ();
reg clk;
reg reset;
reg t;
wire q;
initial begin
clk = 1'b0;
end
always #5 clk = ~clk;
initial begin
reset = 1'b1;
#10 reset = 1'b0;
end
initial begin
t = 1'b0;
#10 t = 1'b1;
end
initial begin
#100 $finish;
end
tff inst(.clk(clk), .reset(reset), .t(t), .q(q));
endmodule
CS450⚓︎
Cs450/timer⚓︎
Website: https://hdlbits.01xz.net/wiki/Cs450/timer
這題單純寫個counter,就結束了。
module top_module(
input clk,
input load,
input [9:0] data,
output tc
);
reg [9:0] counter;
always@(posedge clk)begin
if(load) counter <= data;
else if(counter == 10'd0) counter <= 10'd0;
else counter <= counter - 1'b1;
end
assign tc = (counter == 10'd0);
endmodule
Cs450/counter 2bc⚓︎
Website: https://hdlbits.01xz.net/wiki/Cs450/counter_2bc
這題就是照題目寫FSM,沒什麼難度。
module top_module(
input clk,
input areset,
input train_valid,
input train_taken,
output reg [1:0] state
);
reg [1:0] next_state;
parameter SNT = 2'b00;
parameter WNT = 2'b01;
parameter WT = 2'b10;
parameter ST = 2'b11;
always@(*)begin
if(train_valid)begin
case(state)
SNT: next_state= train_taken? WNT: SNT;
WNT: next_state= train_taken? WT: SNT;
WT: next_state= train_taken? ST: WNT;
ST: next_state= train_taken? ST: WT;
endcase
end
else next_state = state;
end
always@(posedge clk, posedge areset)begin
if(areset) state <= WNT;
else state <= next_state;
end
endmodule
Cs450/history shift⚓︎
Website: https://hdlbits.01xz.net/wiki/Cs450/history_shift
這題就是簡單版的預測分支,題目很長,實際上滿簡單的,考驗英文能力。
module top_module(
input clk,
input areset,
input predict_valid,
input predict_taken,
output reg [31:0] predict_history,
input train_mispredicted,
input train_taken,
input [31:0] train_history
);
always@(posedge clk, posedge areset)begin
if(areset) predict_history <= 32'd0;
else if(train_mispredicted) predict_history <= {train_history[30:0], train_taken};
else if(predict_valid) predict_history <= {predict_history[30:0], predict_taken};
end
endmodule
Cs450/gshare⚓︎
Website: https://hdlbits.01xz.net/wiki/Cs450/gshare
這題就前兩題的綜合題,考驗的是英文閱讀能力,
module top_module(
input clk,
input areset,
input predict_valid,
input [6:0] predict_pc,
output predict_taken,
output [6:0] predict_history,
input train_valid,
input train_taken,
input train_mispredicted,
input [6:0] train_history,
input [6:0] train_pc
);
//update PHT
reg [1:0] PHT [127:0];
wire [6:0]hash;
assign hash = train_pc ^ train_history;
integer i;
always@(posedge clk, posedge areset)begin
if(areset)begin
for(i=0; i<128; i++)begin
PHT[i] <= 2'b01;
end
end
else begin
if(train_taken & train_valid) PHT[hash] <= (PHT[hash] == 2'b11)? 2'b11: PHT[hash] + 2'b01;
else if(~train_taken & train_valid) PHT[hash] <= (PHT[hash] == 2'b00)? 2'b00: PHT[hash] - 2'b01;
end
end
assign predict_taken = PHT[predict_pc ^ predict_history][1];
//update predict history
always@(posedge clk, posedge areset)begin
if(areset) predict_history <= 7'd0;
else if(train_valid & train_mispredicted) predict_history <= {train_history[5:0], train_taken};
else if(predict_valid) predict_history <= {predict_history[5:0], predict_taken};
end
endmodule