module sequence_generator( input clk , input rst_n , output out_sequence );
reg [9:0] sequence ; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin sequence <= 10b0010110111 ; end else begin sequence <= {sequence[8:0],sequence[9]} ; end end
assign out_sequence = sequence[9] ;
endmodule
module sequence_generator_tb ;
reg clk ; reg rst_n ; wire out_sequence ;
initial begin clk = 0 ; rst_n = 1 ; #10 rst_n = 0 ; #10 rst_n = 1 ; end
always #1 clk = ~clk ; sequence_generator sequence_generator( .clk(clk) , .rst_n(rst_n) , .out_sequence(out_sequence) );
2、設計一個自動飲料售賣機,共有兩種飲料,其中飲料A每個10分錢,飲料B每個5分錢,硬幣有5分和10分兩種,並考慮找零。要求用狀態機實現,定義狀態,畫出狀態轉移圖,並用Verilog完整描述該模塊
狀態機如上所示,只完成簡單的功能,沒有描述全所有狀態轉換:
module machine( input clk , input rst_n , input [2:0] button, //button[0] --coin_in ;button[1] --drink_in ;button[2]-- coin_out input coin_in , //0 --5 fen ;1 --10 fen output reg coin_out , //0 --0 fen ;1 --5 fen input drink_in , //0 --5 fen drink ;1 --10 fen drink output reg drink_out //0 --5 fen drink ;1 --10 fen drink
);
parameter [1:0] IDLE = 2b00 , S0 = 2b01 , S1 = 2b10 , S2 = 2b11 ; reg [1:0] current_state , next_state ;
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin current_state <= IDLE ; end else begin current_state <= next_state ;
end end
reg coin_in_reg ,drink_in_reg ; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin coin_out <= 0 ; drink_out <= 0 ;
coin_in_reg <= 0 ; drink_in_reg <= 0 ; end else begin case(current_state) IDLE :begin coin_out <= 0 ; drink_out <= 0 ; drink_in_reg <= 0 ; if(button[0]) begin coin_in_reg <= coin_in ; end else begin coin_in_reg <= 0 ; end end S0 :begin coin_out <= 0 ; drink_out <= 0 ; if(button[1]) begin drink_in_reg <= drink_in ; end else begin drink_in_reg <= 0 ;
end end S1 :begin coin_out <= 0 ; if(coin_in_reg >= drink_in_reg) drink_out <= drink_in_reg ; else drink_out <= 1b0 ; end S2 :begin drink_out <= 0 ; drink_in_reg <= 0 ; if(button[0]) begin coin_in_reg <= coin_in ; end else begin coin_in_reg <= 0 ; end if(coin_in_reg > drink_in_reg) coin_out <= 1b1 ; else coin_out <= 1b0 ; end endcase end end
always@(*) begin next_state = IDLE ; case(current_state) IDLE : begin if(button[0]) begin next_state = S0 ; end else begin next_state = IDLE ; end end S0 : begin if(button[1]) begin next_state = S1 ; end end S1 : begin if(button[2]) begin next_state = S2 ; end end S2 : begin if(button[0]) begin next_state = S0 ; end end endcase end
module machine_tb; reg clk ; reg rst_n ; reg [2:0] button ; reg coin_in ; wire coin_out ; reg drink_in ; wire drink_out ;
initial begin clk = 0 ; rst_n = 1 ; button = 0 ; coin_in = 0 ; drink_in = 0 ; #20 rst_n = 0 ; #20 rst_n = 1 ; #30
@(posedge clk ) #1 button[0] = 1 ; coin_in = 1 ; @(posedge clk ) #1 button[0] = 0 ; coin_in = 0 ; button[1] = 1 ; drink_in = 0 ; @(posedge clk ) #1 button[1] = 0 ; drink_in = 0 ; button[2] = 1 ;
@(posedge clk ) #1 button[2] = 0 ; button[0] = 1 ; coin_in = 1 ; @(posedge clk ) #1 button[0] = 0 ; coin_in = 0 ;
button[1] = 1 ; drink_in = 1 ; @(posedge clk ) #1 button[1] = 0 ; drink_in = 0 ; button[2] = 1 ;
end
always #10 clk = ~clk ;
machine machine( .clk(clk) , .rst_n(rst_n) , .button(button) , .coin_in(coin_in) , .coin_out(coin_out) , .drink_in(drink_in) , .drink_out(drink_out)
3、請實現對(1011001)2的序列檢測功能,模塊每拍並行輸入2bit,且順序為高位先輸入,當檢測到序列,輸出一拍高電平脈衝。請用Verilog描述該模塊。
相當於檢測10_11_00_1X
未描述完所有狀態轉換
module sequence_checker_2bit( input clk , input rst_n, input [1:0] sequence_in , output reg pulse_out );
parameter [2:0] IDLE = 3b000 ,S0= 3b001,S1= 3b010,S2= 3b011,S3= 3b100 ;
reg [2:0] current_state ,next_state ;
reg pulse_out_reg ; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin current_state <= 0 ; pulse_out <= 0 ; end else begin current_state <= next_state ; pulse_out <= pulse_out_reg ; end end
always@(*) begin next_state = IDLE; case(current_state) IDLE : begin if(sequence_in == 2b10) next_state = S0; pulse_out_reg = 0 ; end S0 : begin if(sequence_in == 2b11) next_state = S1; pulse_out_reg = 0 ;
end S1 : begin if(sequence_in == 2b00) next_state = S2; pulse_out_reg = 0 ;
end S2 : begin if(sequence_in == 2b10 || sequence_in == 2b11) begin next_state = S3; pulse_out_reg = 1 ; end end S3 : begin if(sequence_in == 2b10) next_state = S0; else next_state = IDLE; pulse_out_reg = 0 ;
end endcase end
module sequence_checker_2bit_tb ; reg clk ; reg rst_n ; reg [1:0] sequence_in ; wire pulse_out ;
initial begin clk = 0 ; rst_n = 1 ; sequence_in = 2b00 ; #20 rst_n = 0; #20 rst_n = 1 ; @(posedge clk) #1 sequence_in = 2b10 ; @(posedge clk) #1 sequence_in = 2b11 ; @(posedge clk) #1 sequence_in = 2b00 ; @(posedge clk) #1 sequence_in = 2b10 ;
@(posedge clk) #1 @(posedge clk) #1
@(posedge clk) #1 sequence_in = 2b10 ; @(posedge clk) #1 sequence_in = 2b11 ; @(posedge clk) #1 sequence_in = 2b00 ; @(posedge clk) #1 sequence_in = 2b11 ;
sequence_checker_2bit sequence_checker_2bit( .clk(clk) , .rst_n(rst_n), .sequence_in(sequence_in) , .pulse_out(pulse_out) );
4、請基於f = 100Hz的Clock設計一個數字時鐘,用Verilog實現以下功能
1、產生時、分、秒的計時
2、可通過3個按鍵來設置時、分、秒值
module clock( input clk , input rst_n , input hour_set, input [4:0] hour_set_value ,
input minute_set, input [5:0] minute_set_value ,
input second_set , input [5:0] second_set_value ,
output [5:0] second_out , output [5:0] minute_out , output [4:0] hour_out );
reg [5:0] second_reg ; reg [5:0] minute_reg ; reg [4:0] hour_reg ; always@(posedge clk or negedge rst_n ) begin if(!rst_n) begin second_reg <= 0 ; end else if(second_set) second_reg <= second_set_value ; else if(second_reg == 59) second_reg <= 0; else second_reg <= second_reg +1 ; end
always@(posedge clk or negedge rst_n ) begin if(!rst_n) begin minute_reg <= 0 ; end else if(minute_set) minute_reg <= minute_set_value ; else if(minute_reg == 59 && second_reg == 59) minute_reg <= 0; else if(second_reg == 59) minute_reg <= minute_reg +1 ; end
always@(posedge clk or negedge rst_n ) begin if(!rst_n) begin hour_reg <= 0 ; end else if(hour_set) hour_reg <= hour_set_value ; else if(hour_reg == 23 && minute_reg == 59 && second_reg == 59) hour_reg <= 0; else if(minute_reg == 59 && second_reg == 59 ) hour_reg <= hour_reg +1 ; end
assign second_out = second_reg ; assign minute_out = minute_reg; assign hour_out = hour_reg; endmodule
module clock_tb ; reg clk ; reg rst_n ; reg hour_set ; reg [4:0] hour_set_value ; reg minute_set ; reg [5:0]minute_set_value ; reg second_set ; reg [5:0]second_set_value ;
wire [5:0] second_out ; wire [5:0] minute_out ; wire [4:0] hour_out ;
initial begin clk = 0 ; rst_n = 1 ; hour_set = 0 ; hour_set_value = 0; minute_set = 0 ; minute_set_value = 0; second_set = 0 ; second_set_value = 0; #10 rst_n = 0 ; #10 rst_n = 1 ;
@(posedge clk ) #1
hour_set = 1 ; hour_set_value= 10 ; minute_set = 1 ; minute_set_value = 10 ; second_set= 1 ; second_set_value = 10 ; @(posedge clk ) #1 hour_set = 0 ; hour_set_value= 0 ; minute_set = 0 ; minute_set_value = 0 ; second_set= 0 ; second_set_value = 0 ;
always #5 clk =~clk ;
clock clock( .clk(clk) , .rst_n(rst_n) , .hour_set(hour_set) , .hour_set_value(hour_set_value) ,
.minute_set(minute_set), .minute_set_value(minute_set_value) ,
.second_set(second_set), .second_set_value(second_set_value) ,
.second_out(second_out) , .minute_out(minute_out) , .hour_out(hour_out) );
推薦閱讀: