Uploaded by eason911109

作業二

advertisement
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
切換
Download