常见手撕题()

[数字IC手撕verilog]常见手撕题

序列检测

状态机

牛客VL25 输入序列连续的序列检测

// mealy method
`timescale 1ns/1ns
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
   parameter idle = 4'd0, s0 = 4'd1, s1 =4'd2, s2 =4'd3, s3 =4'd4, s4 =4'd5, s5 = 4'd6,
  s6 = 4'd7, s7 = 4'd8;
  
  reg [3:0] state, next_state;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      state <= idle;
    else
      state <= next_state;
  end
  
  always @(*)begin
    case(state)
      idle: next_state = a ? idle : s0;
      s0 : next_state = a ? s1 : s0;
      s1 : next_state = a ? s2 : s0;
      s2 : next_state = a ? s3 : s0;
      s3 : next_state = a ? idle : s4;
      s4 : next_state = a ? s1 : s5;
      s5 : next_state = a ? s1 : s6;
      s6 : next_state = a ? s7 : s0;
      s7 : next_state = a ? s2 : s0;
    endcase
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (state == s7)
      match <= 1'b1;
    else
      match <= 1'b0;
  end
endmodule
// moore method
`timescale 1ns/1ns
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
   parameter idle = 4'd0, s0 = 4'd1, s1 =4'd2, s2 =4'd3, s3 =4'd4, s4 =4'd5, s5 = 4'd6,
  s6 = 4'd7, s7 = 4'd8;
  
  reg [3:0] state, next_state;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      state <= idle;
    else
      state <= next_state;
  end
  
  always @(*)begin
    case(state)
      idle: next_state = a ? idle : s0;
      s0 : next_state = a ? s1 : s0;
      s1 : next_state = a ? s2 : s0;
      s2 : next_state = a ? s3 : s0;
      s3 : next_state = a ? idle : s4;
      s4 : next_state = a ? s1 : s5;
      s5 : next_state = a ? s1 : s6;
      s6 : next_state = a ? s1 : s0;
    endcase
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (state = s6 && a == 1'b1)
      match <= 1'b1;
    else match <= 1'b0;
  end
 endmodule

移位寄存器

牛客VL26 含有无关项的序列检测

`timescale 1ns/1ps
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
  
  reg [8:0] a_reg;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      a_reg <= 1'b0;
    else
      a_reg <= {a_reg[7:0], a};
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (a_reg[8:6] == 3'b011 && a_reg[2:0] == 3'b110)
      match <= 1'b1;
    else 
      match <= 1'b0;
  end
endmodule

斐波那契数列

module fibonacci(
	input clk,
  input rst_n,
  input enable,
  output [31:0] sum
);
  reg [31:0] reg1, reg2, sum;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      reg1 <= 1'b0;
      reg2 <= 1'b0;
    end
    else if (enable)begin
    	if (reg1 == 0 && reg2 == 0)begin
      	reg1 <= 1'b1;
      	reg2 <= 1'b0;
    	end
      else begin
        reg1 <= reg2;
        reg2 <= sum;
      end
    end
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      sum <= 1'b0;
    else if (enable)
      sum <= reg1 + reg2;
  end
endmodule

同步FIFO

`timescale 1ns/1ns
// ------------- dual port ram ----------------------
module dual_port_RAM#(
	parameter WIDTH = 8,
  parameter DEPTH = 16
)(
	input wclk,
  input rclk,
  input wenc,
  input renc,
  input [$clog2(DEPTH)-1:0] waddr,
  input [$clog2(DEPTH)-1:0] raddr,
  input [WIDTH-1:0] datain,
  output reg [WIDTH-1:0] dataout
);
  
  reg [WIDTH-1:0] mem [DEPTH-1:0];
  
  always @(posedge wclk)begin
    if(wenc)
      mem[waddr] <= datain;
  end
  
  always @(posedge rclk) begin
    if(renc)
      dataout <= mem[raddr];
  end
endmodule
// -----------------------------------------------

module sfifo#(
	parameter WIDTH = 8,
  parameter DEPTH = 16
)(
	input clk,
  input rst_n,
  input winc,
  input rinc,
  output reg wfull,
  output reg rempty,
  input [WIDTH-1:0] wdata,
  output [WIDTH-1:0] rdata
);
  parameter ADDR_WIDTH = $clog2(DEPTH);
  reg [ADDR_WIDTH:0] wr_ptr, rd_ptr;
  wire wenc, renc;
  
//  assign full = (wr_ptr - rd_ptr) == DEPTH;
//  assign empty = wr_ptr == rd_ptr;
  assign wenc = !wfull & winc;
  assign renc = !rempty & rinc;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      wfull <= 1'b0;
      rempty <= 1'b0;
    end
    else begin
    	wfull <=  (wr_ptr - rd_ptr) == DEPTH;
      rempty <= wr_ptr == rd_ptr;
    end
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
  		wr_ptr <= 1'b0;
    else if(wenc)
      wr_ptr <= wr_ptr + 1'b1;
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      rd_ptr <= 1'b0;
    else if (renc)
      rd_ptr <= rd_ptr + 1'b1;
  end
  
  dual_port_RAM #(.WIDTH(WIDTH), .DEPTH(DEPTH))
  inst (
    clk, clk, wenc, renc, wr_ptr[ADDR_WIDTH-1:0], rd_ptr[ADDR_WIDTH-1:0],
    wdata, rdata
  );
endmodule

深度为1的FIFO

超前加法器

// S = A^B^Cin Cout = A&B + (A^B)&C
// so let P = A^B, G = A&B
module lca(
  input [3:0] A,
  input [3:0] B,
  input Cin,
  
  output Cout,
  output [3:0] sum
);
  wire [3:0] g, p, carry;
  assign g = A & B;
  assign p = A ^ B;
  
  assign sum[0] = p[0] ^ Cin;
  assign sum[1] = p[1] ^ carry[0];
  assign sum[2] = p[2] ^ carry[1];
  assign sum[3] = p[3] ^ carry[2];
  
  assign carry[0] = g[0] | (p[0] & Cin);
  assign carry[1] = g[1] | (p[1] & carry[0]);
  assign carry[2] = g[2] | (p[2] & carry[1]);
  assign carry[3] = g[3] | (p[3] & carry[2]);
  
  assign Cout = carry[3];
endmodule

握手反压

仲裁器

fixed arbiter

module fixed_arb#(
	parameter REQ_WIDTH = 16
)(
  input [REQ_WIDTH-1:0] req,
  output [REQ_WIDTH-1:0] gnt
);
  assign gnt = req & (~(req-1));
endmodule
#include <iostream>

int main()
{
	int req[4] = {0,0,0,0};
	
int i = 0;
while (i < 4)
{
	if(req[i]==1)
	{
	gnt[i] = 1;
	break;
}
}
}

prior_arb

module rrab#(
	parameter NUM_REQ = 4
)(
	input clk,
	input rstn,
	input [NUM_REQ-1:0] req,
	output [NUM_REQ-1:0] gnt 
);
	reg [NUM_REQ-1:0] hist_q;
	
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)
			hist_q <= 1'b1;
		else
			hist_q <= {gnt[NUM_REQ-2:0], gnt[NUM_REQ-1]};
	end
	
	arb_base #(.NUM_REQ(NUM_REQ))
	inst
	(
		req,
		gnt,
		base(hist_q)
	);
endmdoule

arb_base
(
	input req,
	output gnt,
	input base
);
	wire [2*NUM_REQ-1:0] double_req = {req,req};
	wire [2*NUM_REQ-1:0] double_gnt = double_req & ~(double_req - base);
	assign gnt = double_gnt[NUM_REQ-1:0] | double_gnt[2*NUM_REQ-1:NUM_REQ];
endmodule
————————

[数字IC手撕verilog]常见手撕题

序列检测

状态机

牛客VL25 输入序列连续的序列检测

// mealy method
`timescale 1ns/1ns
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
   parameter idle = 4'd0, s0 = 4'd1, s1 =4'd2, s2 =4'd3, s3 =4'd4, s4 =4'd5, s5 = 4'd6,
  s6 = 4'd7, s7 = 4'd8;
  
  reg [3:0] state, next_state;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      state <= idle;
    else
      state <= next_state;
  end
  
  always @(*)begin
    case(state)
      idle: next_state = a ? idle : s0;
      s0 : next_state = a ? s1 : s0;
      s1 : next_state = a ? s2 : s0;
      s2 : next_state = a ? s3 : s0;
      s3 : next_state = a ? idle : s4;
      s4 : next_state = a ? s1 : s5;
      s5 : next_state = a ? s1 : s6;
      s6 : next_state = a ? s7 : s0;
      s7 : next_state = a ? s2 : s0;
    endcase
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (state == s7)
      match <= 1'b1;
    else
      match <= 1'b0;
  end
endmodule
// moore method
`timescale 1ns/1ns
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
   parameter idle = 4'd0, s0 = 4'd1, s1 =4'd2, s2 =4'd3, s3 =4'd4, s4 =4'd5, s5 = 4'd6,
  s6 = 4'd7, s7 = 4'd8;
  
  reg [3:0] state, next_state;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      state <= idle;
    else
      state <= next_state;
  end
  
  always @(*)begin
    case(state)
      idle: next_state = a ? idle : s0;
      s0 : next_state = a ? s1 : s0;
      s1 : next_state = a ? s2 : s0;
      s2 : next_state = a ? s3 : s0;
      s3 : next_state = a ? idle : s4;
      s4 : next_state = a ? s1 : s5;
      s5 : next_state = a ? s1 : s6;
      s6 : next_state = a ? s1 : s0;
    endcase
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (state = s6 && a == 1'b1)
      match <= 1'b1;
    else match <= 1'b0;
  end
 endmodule

移位寄存器

牛客VL26 含有无关项的序列检测

`timescale 1ns/1ps
module sequence_detect(
	input clk,
  input rst_n,
  input a,
  output reg match
);
  
  reg [8:0] a_reg;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      a_reg <= 1'b0;
    else
      a_reg <= {a_reg[7:0], a};
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      match <= 1'b0;
    else if (a_reg[8:6] == 3'b011 && a_reg[2:0] == 3'b110)
      match <= 1'b1;
    else 
      match <= 1'b0;
  end
endmodule

斐波那契数列

module fibonacci(
	input clk,
  input rst_n,
  input enable,
  output [31:0] sum
);
  reg [31:0] reg1, reg2, sum;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      reg1 <= 1'b0;
      reg2 <= 1'b0;
    end
    else if (enable)begin
    	if (reg1 == 0 && reg2 == 0)begin
      	reg1 <= 1'b1;
      	reg2 <= 1'b0;
    	end
      else begin
        reg1 <= reg2;
        reg2 <= sum;
      end
    end
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      sum <= 1'b0;
    else if (enable)
      sum <= reg1 + reg2;
  end
endmodule

同步FIFO

`timescale 1ns/1ns
// ------------- dual port ram ----------------------
module dual_port_RAM#(
	parameter WIDTH = 8,
  parameter DEPTH = 16
)(
	input wclk,
  input rclk,
  input wenc,
  input renc,
  input [$clog2(DEPTH)-1:0] waddr,
  input [$clog2(DEPTH)-1:0] raddr,
  input [WIDTH-1:0] datain,
  output reg [WIDTH-1:0] dataout
);
  
  reg [WIDTH-1:0] mem [DEPTH-1:0];
  
  always @(posedge wclk)begin
    if(wenc)
      mem[waddr] <= datain;
  end
  
  always @(posedge rclk) begin
    if(renc)
      dataout <= mem[raddr];
  end
endmodule
// -----------------------------------------------

module sfifo#(
	parameter WIDTH = 8,
  parameter DEPTH = 16
)(
	input clk,
  input rst_n,
  input winc,
  input rinc,
  output reg wfull,
  output reg rempty,
  input [WIDTH-1:0] wdata,
  output [WIDTH-1:0] rdata
);
  parameter ADDR_WIDTH = $clog2(DEPTH);
  reg [ADDR_WIDTH:0] wr_ptr, rd_ptr;
  wire wenc, renc;
  
//  assign full = (wr_ptr - rd_ptr) == DEPTH;
//  assign empty = wr_ptr == rd_ptr;
  assign wenc = !wfull & winc;
  assign renc = !rempty & rinc;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      wfull <= 1'b0;
      rempty <= 1'b0;
    end
    else begin
    	wfull <=  (wr_ptr - rd_ptr) == DEPTH;
      rempty <= wr_ptr == rd_ptr;
    end
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
  		wr_ptr <= 1'b0;
    else if(wenc)
      wr_ptr <= wr_ptr + 1'b1;
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      rd_ptr <= 1'b0;
    else if (renc)
      rd_ptr <= rd_ptr + 1'b1;
  end
  
  dual_port_RAM #(.WIDTH(WIDTH), .DEPTH(DEPTH))
  inst (
    clk, clk, wenc, renc, wr_ptr[ADDR_WIDTH-1:0], rd_ptr[ADDR_WIDTH-1:0],
    wdata, rdata
  );
endmodule

深度为1的FIFO

超前加法器

// S = A^B^Cin Cout = A&B + (A^B)&C
// so let P = A^B, G = A&B
module lca(
  input [3:0] A,
  input [3:0] B,
  input Cin,
  
  output Cout,
  output [3:0] sum
);
  wire [3:0] g, p, carry;
  assign g = A & B;
  assign p = A ^ B;
  
  assign sum[0] = p[0] ^ Cin;
  assign sum[1] = p[1] ^ carry[0];
  assign sum[2] = p[2] ^ carry[1];
  assign sum[3] = p[3] ^ carry[2];
  
  assign carry[0] = g[0] | (p[0] & Cin);
  assign carry[1] = g[1] | (p[1] & carry[0]);
  assign carry[2] = g[2] | (p[2] & carry[1]);
  assign carry[3] = g[3] | (p[3] & carry[2]);
  
  assign Cout = carry[3];
endmodule

握手反压

仲裁器

fixed arbiter

module fixed_arb#(
	parameter REQ_WIDTH = 16
)(
  input [REQ_WIDTH-1:0] req,
  output [REQ_WIDTH-1:0] gnt
);
  assign gnt = req & (~(req-1));
endmodule
#include <iostream>

int main()
{
	int req[4] = {0,0,0,0};
	
int i = 0;
while (i < 4)
{
	if(req[i]==1)
	{
	gnt[i] = 1;
	break;
}
}
}

prior_arb

module rrab#(
	parameter NUM_REQ = 4
)(
	input clk,
	input rstn,
	input [NUM_REQ-1:0] req,
	output [NUM_REQ-1:0] gnt 
);
	reg [NUM_REQ-1:0] hist_q;
	
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)
			hist_q <= 1'b1;
		else
			hist_q <= {gnt[NUM_REQ-2:0], gnt[NUM_REQ-1]};
	end
	
	arb_base #(.NUM_REQ(NUM_REQ))
	inst
	(
		req,
		gnt,
		base(hist_q)
	);
endmdoule

arb_base
(
	input req,
	output gnt,
	input base
);
	wire [2*NUM_REQ-1:0] double_req = {req,req};
	wire [2*NUM_REQ-1:0] double_gnt = double_req & ~(double_req - base);
	assign gnt = double_gnt[NUM_REQ-1:0] | double_gnt[2*NUM_REQ-1:NUM_REQ];
endmodule