数字IC手撕代码(六)

之前看到过一个题目是说让做一个序列发生器:产生序列信号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

数字IC手撕代码(六)_第1张图片

你可能感兴趣的:(数字IC手撕代码(六))