module hw2_1 ( R, L, clk, Qout ); 建立⼀個 mux_dff 的實體 instance0 instance0 使⽤ Qout[2]、R[0]、L、clk 作為輸入,並將結果儲存在 Qout[0] input [2:0] R; input L; input clk; output [2:0] Qout; wire xor_out; 對 Qout[1] 和 Qout[2] 做 XOR 運算,結果儲存在 xor_out mux_dff instance0 ( .M0( Qout[2] ), .M1( R[0] ), .sel( L ), .clk( clk ), .dff_out( Qout[0] ) ); mux_dff instance1 ( .M0( Qout[0] ), .M1( R[1] ), .sel( L ), .clk( clk ), .dff_out( Qout[1] ) ); xor( xor_out, Qout[1], Qout[2] ); 建立⼀個 mux_dff 的實體 instance1 instance1 使⽤ Qout[0]、R[1]、L、clk 作為輸入,並將 結果儲存在 Qout[1] mux_dff instance2 ( .M0( xor_out ), .M1( R[2] ), .sel( L ), .clk( clk ), .dff_out( Qout[2] ) ); endmodule module mux_dff ( //module of one mux and one dff M0, M1, sel, clk, dff_out ); input M0; input M1; input sel; input clk; output reg dff_out = 0; output reg outdff ' " 建立⼀個 mux_dff 的實體 instance2 instance2 使⽤ xor_out、R[2]、L、clk 作為輸入,並將結果儲 存在 Qout[2] " " = 0 ; - reg mux_out = 0; always@(*)begin , , 預設輸出為 0 的暫存器 結構區塊內的程式碼會在任何輸入有變化時執⾏ case (sel) 0 : mux_out = M0; 1 : mux_out = M1; endcase end 如果 sel 為 0,將 M0 輸出到 mux_out 如果 sel 為 1,將 M1 輸出到 mux_out always@(posedge clk)begin dff_out = mux_out; end endmodule , 結構區塊內的程式碼會在時鐘上 升邊緣觸發時執⾏ 0 將 mux_out 的值輸出到 dff_out `timescale 1 ns/1 ns 設定時序,表⽰時間單位為 1 ns module hw2_2(clk, reset, data_in, c, data_out); input clk, reset; input[7:0] data_in; input[8:0] c; ← 類似 selector output[7:0] data_out; reg[7:0] r0, r1, r2, r_out; reg[7:0]src_a, src_b, dest; 8 位元的暫存器 r0、r1、r2 和 r_out 8 位元的暫存器 src_a、src_b 和 dest always@(*)begin 當任何輸入有變化時執⾏的結構區塊 // the upper mux => use c[4:3] to select value 上⽅的多路選擇器(MUX)=> 使⽤ c[4:3] 選擇數值 case(c[4:3]) 2'b00: src_a = r0; 如果 c[4:3] 為 2'b00,將 r0 輸出到 src_a 2'b01: src_a = r1; 如果 c[4:3] 為 2'b01,將 r1 輸出到 src_a 2'b10: src_a = r2; 如果 c[4:3] 為 2'b10,將 r2 輸出到 src_a 2'b11: src_a = data_in; 如果 c[4:3] 為 2'b11,將 data_in 輸出到 src_a endcase 下⽅的多路選擇器(MUX)=> 使⽤ c[6:5] 選擇數值 // the down mux => use c[6:5] to select value case(c[6:5]) 如果 c[6:5] 為 2'b00,將 r0 輸出到 src_b 2'b00: src_b = r0; 如果 c[6:5] 為 2'b01,將 r1 輸出到 src_b 2'b01: src_b = r1; 如果 c[6:5] 為 2'b10,將 r2 輸出到 src_b 2'b10: src_b = r2; 2'b11: src_b = data_in; 如果 c[6:5] 為 2'b11,將 data_in 輸出到 src_b endcase 右⽅的多路選擇器(MUX)=> 使⽤ c[2:0] 選擇運算 // the right mux => use c[2:0] to select operand case(c[2:0]) 3'b000: dest = src_a; 如果 c[2:0] 為 3'b000,將 src_a 輸出到 dest 3'b001: dest = src_a + src_b; 如果 c[2:0] 為 3'b001,將 src_a 和 src_b 相加後輸出到 dest 3'b010: dest = src_a - src_b; 如果 c[2:0] 為 3'b010,將 src_a 減去 src_b 後輸出到 dest 3'b011: dest = src_a & src_b; 如果 c[2:0] 為 3'b011,將 src_a 和 src_b 進⾏位元 AND 運算後輸出到 dest 3'b100: dest = src_a | src_b; 如果 c[2:0] 為 3'b100,將 src_a 和 src_b 進⾏位元 OR 運算後輸出到 dest 3'b101: dest = src_a ^ src_b; 如果 c[2:0] 為 3'b101,將 src_a 和 src_b 進⾏位元 XOR 運算後輸出到 dest endcase end //wiring up data_out with register r_out => output the answer 將 data_out 與寄存器 r_out 連接起來 => 輸出答案 assign data_out = r_out; 懇 always@(posedge clk or negedge reset)begin 當時鐘上升邊緣觸發或 reset 下降邊緣觸發時執⾏的結構區塊 if(~reset)begin // initialize all registers => zero 初始化所有寄存器 => 設為零 posedge cdk r0 <= 8'h00; r1 <= 8'h00; negedge reset r2 <= 8'h00; r_out <= 8'h00; end 左⽅的多路選擇器(MUX)=> 使⽤ c[8:7] 選擇需要修改的寄存器 else begin // the left mux => use c[8:7] to select which register need to be modified case(c[8:7]) 2'b00: r0 <= dest; 如果 c[8:7] 為 2'b00,將 dest 輸出到 r0 2'b01: r1 <= dest; 如果 c[8:7] 為 2'b01,將 dest 輸出到 r1 2'b10: r2 <= dest; 2'b11: r_out <= dest; 如果 c[8:7] 為 2'b10,將 dest 輸出到 r2 endcase 如果 c[8:7] 為 2'b11,將 dest 輸出到 r_out end end endmodule module hw2_3( input clk, input areset, input turn_left, input turn_right, input ground, output reg walk_left, output reg walk_right, output reg aaah ); reg [1:0]state,next; // 輸入: input clk; // 時鐘輸入 input areset; // 歸零輸入 input turn_left; // 向左轉輸入 input turn_right; // 向右轉輸入 input ground; // 地⾯狀態輸入 // 輸出: output reg walk_left; // 向左⾏走輸出 output reg walk_right; // 向右⾏走輸出 output reg aaah; // 表⽰驚訝狀態的輸出 // write your codes //state 宣告狀態寄存器 //LEFT => walk left //RIGHT => walk right //FALL_L => Before falling, the previous state is LEFT (walk left) //FALL_R => Before falling, the previous state is RIGHT (wlak right) parameter LEFT = 0, RIGHT = 1, FALL_L = 2, FALL_R = 3; 宣告狀態常數 always@(*)begin //according attributes of each state, produce the correct output 根據每個狀態的屬性產⽣正確的輸出 case(state) LEFT: {aaah, walk_left, walk_right} = 3'b010; // Left: aaah = 0, walk_left = 1, wlak_right = 0 RIGHT: {aaah, walk_left, walk_right} = 3'b001; // Right: aaah = 0, walk_left = 0, wlak_right = 1 FALL_L: {aaah, walk_left, walk_right} = 3'b100; // Fall : aaah = 1, walk_left = 0, wlak_right = 0 FALL_R: {aaah, walk_left, walk_right} = 3'b100; // Fall : aaah = 1, walk_left = 0, wlak_right = 0 endcase end 有 // the turning condtion of each state always@(*)begin if(state == LEFT)begin // Left state if(ground == 1'b0) // if ground == 0'b0 => fall next <= FALL_L; else if(turn_left & turn_right) next <= RIGHT; else if(turn_right) next <= RIGHT; else next <= LEFT; end else if(state == RIGHT)begin if(ground == 1'b0) next <= FALL_R; else if(turn_left & turn_right) next <= LEFT; else if(turn_left) next <= LEFT; else next <= RIGHT; end begin 就有 end 當狀態為 LEFT時,如果 ground 為 0,表⽰掉落 如果同時發⽣ turn_left 和 turn_right,則切換⽅向,從左轉向右 如果只有發⽣ turn_right,切換⽅向,從左轉向右 剩下發⽣turn_left,保持原有⽅向,仍為左 // both turn_left and turn_right are occuring // => switch direction from left to right // turn_right is occuring // => switch direction from left to right // remain the direction => left // Right state // if ground == 0'b0 => fall // both turn_left and turn_right are occuring // => switch direction from right to left // trun_left is occuring // => switch direction from right to left // remain the direction => right 當狀態為 RIGHT 時,如果 ground 為 0,表⽰掉落 如果同時發⽣ turn_left 和 turn_right,則切換⽅向,從右轉向左 如果只有發⽣ turn_left,切換⽅向,從右轉向左 剩下的保持原有⽅向,仍為右 else if(state == FALL_L)begin 當狀態為 FALL_L 時,即從向左⾏走掉落 // Falling from walking left 如果 ground 為 1,表⽰落地,則回到向左⾏走狀態 if(ground == 1'b1) // if ground == 1'b1 其他則保持掉落狀態,也就是尚未落地。 next <= LEFT; // => back to walking left else // if not next <= FALL_L; //=> keep falling end else if(state == FALL_R)begin // Falling from walking right 當狀態為 FALL_R 時,即從向右⾏走掉落 if(ground == 1'b1) // if ground == 1'b0 next <= RIGHT; //=> back to walking right 如果 ground 為 1,表⽰落地,則回到向右⾏走狀態 else // if not 剩下的則保持掉落狀態,也就是尚未落地。 next <= FALL_R; // => keep falling end else next <= LEFT; // default value 預設為向左⾏走狀態 end //finite state always@(posedge clk or posedge areset)begin if(areset) state <= LEFT; // initialize state else state <= next; // change state end endmodule 初始化狀態為 LEFT 切換