之前看到过一个题目是说让做一个序列发生器:产生序列信号11010111
**第一种方法:**利用移位寄存器实现
module seq_gen(
input clk,
input rst_n,
output dout
);
reg [7:0] seq_out;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
seq_out <= 8'b1101_0111;
end
else begin
seq_out <= {seq_out[6:0],seq_out[7]};
end
end
assign dout = seq_out[7];
endmodule
**第二种方法:**利用计数器
module seq_gen(
input clk,
input rst_n,
output dout
);
reg [2:0] cnt;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 3'd0;
end
else if(cnt==3'd7) begin
cnt <= 3'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
always @ (*) begin
case(cnt)
3'd0 : dout = 1;
3'd1 : dout = 1;
3'd2 : dout = 0;
3'd3 : dout = 1;
3'd4 : dout = 0;
3'd5 : dout = 1;
3'd6 : dout = 1;
3'd7 : dout = 1;
default : dout = 0;
endcase
end
endmodule
这个其实就和状态机差不多了,利用状态机实现也类似的方法。8个状态
接下来一个题目是序列检测:10110011
**第一种方法:**利用移位寄存器实现
module seq_check(
input clk,
input rst_n,
input din
output dout
);
reg [7:0] data;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
data <= 8'd0;
end
else begin
data <= {data[6:0],din};
end
end
assign dout = (data==8'b10110011) ? 1'b1 : 1'b0;
endmodule
第二种方法: 状态机
module seq_check(
input clk,
input rst_n,
input din,
output reg dout
);
parameter IDLE = 3'd0;
parameter S1 = 3'd1;
parameter S2 = 3'd2;
parameter S3 = 3'd3;
parameter S4 = 3'd4;
parameter S5 = 3'd5;
parameter S6 = 3'd6;
parameter S7 = 3'd7;
reg [2:0] n_state;
reg [2:0] c_state;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
c_state <= IDLE;
end
else begin
c_state <= n_state;
end
end
always @ (*) begin
case(c_state)
IDLE : if(din) n_state = S1;
else n_state = IDLE;
S1 : if(din) n_state = S1;
else n_state = S2;
S2 : if(din) n_state = S3;
else n_state = IDLE;
S3 : if(din) n_state = S4;
else n_state = S2;
S4 : if(din) n_state = S1;
else n_state = S5;
S5 : if(din) n_state = S3;
else n_state = S6;
S6 : if(din) n_state = S7;
else n_state = IDLE;
S7 : if(din) n_state = S1;
else n_state = S2;
default : n_state = IDLE;
endcase
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout <= 1'b0;
end
else if(c_state==S7 && din) begin
dout <= 1'b1;
end
else begin
dout <= 1'b0;
end
end
endmodule
还有一种这样的题型,类似序列检测,不过输入是2bit。
序列检测:1011001
第一种方法: 移位寄存器
module seq_check(
input clk,
input rst_n,
input [1:0] din
output dout
);
//1011001
reg [7:0] data;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
data <= 8'd0;
end
else begin
data <= {data[5:0],din};
end
end
assign dout = (data[6:0]==7'b10110011 || data[7:1]==7'b1011001) ? 1'b1 : 1'b0;
endmodule
第二种方法: 状态机
输入是并行2bit的话,状态机就稍微麻烦点了。
`timescale 1ns/1ps
module two_bit_input_seq_detector
(
input clk,
input rst_n,
input [1:0] data,
output reg success
);
reg [2:0] current_state;
reg [2:0] next_state;
parameter S0 = 3'b000,
S1 = 3'b001,
S10 = 3'b011,
S101 = 3'b010,
S1011 = 3'b110,
S10110 = 3'b111,
S101100 = 3'b101;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) current_state <= 3'b0;
else current_state <= next_state;
end
always @(*)
case(current_state)
S0,S101100:
case(data)
2'b00: next_state = S0;
2'b01: next_state = S1;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
S1: case(data)
2'b00: next_state = S0;
2'b01: next_state = S101;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
S10,S10110:
case(data)
2'b00: next_state = S0;
2'b01: next_state = S1;
2'b10: next_state = S10;
2'b11: next_state = S1011;
endcase
S101: case(data)
2'b00: next_state = S0;
2'b01: next_state = S101;
2'b10: next_state = S10110;
2'b11: next_state = S1;
endcase
S1011: case(data)
2'b00: next_state = S101100;
2'b01: next_state = S101;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
default: next_state = S0;
endcase
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
success <= 0;
end else begin
case(current_state)
S0,S1,S10,S101,S1011: success <= 0;
S10110 : if(data == 2'b01) success <= 1;
else success <= 0;
S101100: if(data[1] == 1'b1) success <= 1;
else success <= 0;
default: success <= 0;
endcase
end
end
endmodule