設計一個序列信號發生器電路,能在CLK信號作用下周期性輸出「0010110111」的序列信號

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)
);

endmodule

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

endmodule

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)

);

endmodule

  1. 用戶必須按照投幣-買飲料-找零的順序依次操作
  2. 每輪購買操作中,用戶只能投幣一次,不然會發生吞幣!(哈哈~~~)
  3. 投幣大小不能比購買飲料的價格小

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

endmodule

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 ;

end

always #10 clk = ~clk ;

sequence_checker_2bit sequence_checker_2bit(
.clk(clk) ,
.rst_n(rst_n),
.sequence_in(sequence_in) ,
.pulse_out(pulse_out)
);

endmodule

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 ;

end

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)
);

endmodule

推薦閱讀:

相关文章