常见手撕题
作者:互联网
[数字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
标签:撕题,clk,常见,reg,carry,rst,input,assign 来源: https://www.cnblogs.com/pu1se/p/16558220.html