# 常见手撕题()-其他

## 常见手撕题()

### 状态机

``````// 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
``````

### 移位寄存器

```````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 [WIDTH-1:0] datain,
output reg [WIDTH-1:0] dataout
);

reg [WIDTH-1:0] mem [DEPTH-1:0];

always @(posedge wclk)begin
if(wenc)
end

always @(posedge rclk) begin
if(renc)
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
);
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 (
wdata, rdata
);
endmodule
``````

### 超前加法器

``````// 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
``````
————————

### 状态机

``````// 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
``````

### 移位寄存器

```````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 [WIDTH-1:0] datain,
output reg [WIDTH-1:0] dataout
);

reg [WIDTH-1:0] mem [DEPTH-1:0];

always @(posedge wclk)begin
if(wenc)
end

always @(posedge rclk) begin
if(renc)
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
);
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 (
wdata, rdata
);
endmodule
``````

### 超前加法器

``````// 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
``````