之前刷过HDLbits上面的题目,点击链接可以查看详细笔记:verilog练习:hdlbits网站系列完结!
最近又想刷一下牛客上面的题目,可以点击链接与小编一起刷题:牛客刷题
小编不才,文中如有不当之处,可以在评论中互相交流。此处题目推荐看牛客的评论区,再提一嘴,注意积累自己的基本功算法、设计模式、软件等
`timescale 1ns/1ns
module RTL(
input clk,
input rst_n,
input data_in,
output reg data_out
);
reg data_in_reg;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_in_reg <= 'd0;
end else begin
data_in_reg <= data_in;
end
end
assign always1 = data_in & ~data_in_reg;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_out <= 'd0;
end else begin
data_out <= always1;
end
end
endmodule
`timescale 1ns/1ns
module data_driver(
input clk_a,
input rst_n,
input data_ack,
output reg [3:0]data,
output reg data_req
);
reg data_ack_reg_1,data_ack_reg_2;
always @ (posedge clk_a or negedge rst_n)
if (!rst_n)
begin
{data_ack_reg_1,data_ack_reg_2} <= 'd0;
end
else
begin
{data_ack_reg_1,data_ack_reg_2} <= {data_ack,data_ack_reg_1};
end
// wire flag = data_ack_reg_1 && !data_ack_reg_2;
wire flag = {data_ack_reg_1,data_ack_reg_2} == 2'b10;
always @ (posedge clk_a or negedge rst_n)
if (!rst_n) begin
data <= 0;
end
else if(flag)begin
// if(data == 'd7)
// data <= 'd0;
data <= data+1;
end
else begin
data <= data;
end
reg [2:0] cnt;
//同时在data_ack有效之后,开始计数五个时钟,之后发送新的数据,也就是再一次拉高data_req.
always @ (posedge clk_a or negedge rst_n)
if (!rst_n)
cnt <= 0;
else if (flag)
cnt <= 0;
else if (data_req)
cnt <= cnt;
else
cnt <= cnt+1;
always @ (posedge clk_a or negedge rst_n)
if (!rst_n)
data_req <= 0;
else if (cnt == 3'd4)
data_req <= 1'b1;
else if (flag)
data_req <= 1'b0;
else
data_req <= data_req;
endmodule
module data_receiver(
input clk_b,
input rst_n,
output reg data_ack,
input [3:0]data,
input data_req
);
reg [3:0]data_in_reg;
reg data_req_reg_1, data_req_reg_2;
always @ (posedge clk_b or negedge rst_n)
if (!rst_n)begin
{data_req_reg_1, data_req_reg_2} <= 'd0;
end
else begin
{data_req_reg_1, data_req_reg_2} <= {data_req, data_req_reg_1};
end
wire flag = {data_req_reg_1, data_req_reg_2} == 2'b10;
always @ (posedge clk_b or negedge rst_n)
if (!rst_n)
data_ack <= 0;
else if (flag)
data_ack <= 1;
else data_ack <=0 ;
always @ (posedge clk_b or negedge rst_n)
if (!rst_n)
data_in_reg <= 0;
else if (flag)
data_in_reg <= data;
else data_in_reg <= data_in_reg ;
endmodule
`timescale 1ns/1ns
module sale(
input clk ,
input rst_n ,
input sel ,//sel=0,5$dranks,sel=1,10&=$drinks
input [1:0] din ,//din=1,input 5$,din=2,input 10$
output reg [1:0] drinks_out,//drinks_out=1,output 5$ drinks,drinks_out=2,output 10$ drinks
output reg change_out
);
reg [2:0] c_state,n_state;
parameter IDLE = 3'd0;
parameter S1 = 3'd1;//5元买5元饮料
parameter S2 = 3'd2;//10元买5元饮料找5块
parameter S3 = 3'd3;//5元买十元饮料
parameter S4 = 3'd4;//加了5块,不找
parameter S5 = 3'd5;//加了10块,找5块
always@(posedge clk or negedge rst_n)
if(!rst_n)
c_state<=IDLE;
else
c_state <= n_state;
always@(*)
if(sel== 1'b0)begin
case(c_state)
IDLE:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S1;
2'b10: n_state <= S2;
endcase
end
S1:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S1;
2'b10: n_state <= S2;
endcase
end
S2:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S1;
2'b10: n_state <= S2;
endcase
end
S3:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= IDLE;
2'b10: n_state <= IDLE;
endcase
end
S4:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= IDLE;
2'b10: n_state <= IDLE;
endcase
end
S5:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= IDLE;
2'b10: n_state <= IDLE;
endcase
end
endcase
end
else begin
case(c_state)
IDLE:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S3;
2'b10: n_state <= S4;
endcase
end
S1:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= IDLE;
2'b10: n_state <= IDLE;
endcase
end
S2:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= IDLE;
2'b10: n_state <= IDLE;
endcase
end
S3:begin
case(din)
2'b00: n_state <= S3;
2'b01: n_state <= S4;
2'b10: n_state <= S5;
endcase
end
S4:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S3;
2'b10: n_state <= S4;
endcase
end
S5:begin
case(din)
2'b00: n_state <= IDLE;
2'b01: n_state <= S3;
2'b10: n_state <= S4;
endcase
end
endcase
end
always@(*)
if(!rst_n)begin
drinks_out <= 0;
change_out <=0;
end
else begin
case(c_state)
IDLE:begin
drinks_out <= 0;
change_out <=0;
end
S1:begin
drinks_out <= 2'd1;
change_out <=1'd0;
end
S2:begin
drinks_out <= 2'd1;
change_out <=1'd1;
end
S3:begin
drinks_out <= 0;
change_out <=0;
end
S4:begin
drinks_out <=2'd2;
change_out <=0;
end
S5:begin
drinks_out <= 2'd2;
change_out <=1'd1;
end
endcase
end
endmodule
`timescale 1ns/1ns
module sale(
input clk ,
input rst_n ,
input sel ,//sel=0,5$dranks,sel=1,10&=$drinks
input [1:0] din ,//din=1,input 5$,din=2,input 10$
output reg [1:0] drinks_out,//drinks_out=1,output 5$ drinks,drinks_out=2,output 10$ drinks
output reg change_out
);
parameter IDLE = 2'd0;//0元
parameter S1 = 2'd1;//5元
parameter S2 = 2'd2;//10元
parameter S3 = 2'd3;//15元
//第一段
reg [1:0] cur_state, next_state;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cur_state <= IDLE;
end
else begin
cur_state <= next_state;
end
end
//第二段
always@(*) begin
case(cur_state)
IDLE:begin
if(din == 2'b01)
next_state = S1;
else if(din == 2'b10)
next_state = S2;
else
next_state = next_state;
end
S1:begin
if(sel == 0)//买5元的
next_state = IDLE;
else if(din == 2'b01)
next_state = S2;
else if(din == 2'b10)
next_state = S3;
else
next_state = next_state;
end
S2:begin
next_state = IDLE;
end
S3:begin
next_state = IDLE;
end
default: next_state = IDLE;
endcase
end
//第三段
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
{drinks_out,change_out} <= 3'b00_0;
end
else case(next_state)
IDLE:begin
{drinks_out,change_out} <= 3'b00_0;
end
S1:begin
if(sel == 0)//买5元的
{drinks_out,change_out} <= 3'b01_0;
else
{drinks_out,change_out} <= 3'b00_0;
end
S2:begin
if(sel == 0)//买5元的
{drinks_out,change_out} <= 3'b01_1;
else
{drinks_out,change_out} <= 3'b10_0;
end
S3:begin
{drinks_out,change_out} <= 3'b10_1;
end
default:{drinks_out,change_out} <= 3'b00_0;
endcase
end
endmodule
`timescale 1ns/1ns
module sequence_generator(
input clk,
input rst_n,
output reg data
);
reg [5:0] data_reg;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
data_reg <= 6'b001011;
else
data_reg <= {data_reg, data_reg[5]};
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
data <= 1'b0;
else
data <= data_reg[5];
end
endmodule
`timescale 1ns/1ns
module huawei5(
input wire clk ,
input wire rst ,
input wire [3:0]d ,
output wire valid_in ,
output wire dout
);
//*************code***********//
reg [3:0] data = 'd0;
reg [1:0]cnt;//计数
reg valid;
assign dout = data[3];//data的最高位接输出线
assign valid_in =valid;
always @(posedge clk or negedge rst) begin
if(!rst)begin
data<= 'd0;
cnt <= 'd0;
valid <= 'd0;
end
else begin
if (cnt == 'd3) begin
data <= d;//d是在cnt清零时给到data上传的
cnt <= 'd0;
valid <= 1;
end
else begin
cnt <= cnt + 'd1;
valid <= 0;
data <= {data[2:0],data[3]};//循环左移
end
end
end
//*************code***********//
endmodule
从高位移位输出
,4个bit为一个周期。具体的做法就是:利用循环左移将高位移动到低位,然后利用互相寄存的特性,使得最高位寄存输出。`timescale 1ns/1ns
module huawei6(
input wire clk0 ,
input wire clk1 ,
input wire rst ,
input wire sel ,
output wire clk_out
);
reg q0, q1;
always@(negedge clk1 or negedge rst)
if(!rst)
q0 <= 0;
else
q0 <= ~sel & ~q1;
always@(negedge clk0 or negedge rst)
if(!rst)
q1 <= 0;
else
q1 <= sel & ~q0;
assign clk_out = (q0 & clk0) | (q1 & clk1);
endmodule
题目描述: 使用状态机实现时钟分频,要求对时钟进行四分频,占空比为0.25
信号示意图:
clk为时钟
rst为低电平复位
clk_out 信号输出
Ps 本题题解是按照1000的状态转移进行的,不按照此状态进行,编译器可能报错但没有影响。
波形示意图:
输入描述:
clk为时钟
rst为低电平复位
输出描述:
clk_out 信号输出
`timescale 1ns/1ns
module huawei7(
input wire clk ,
input wire rst ,
output reg clk_out
);
//*************code***********//
parameter S0 = 'd0;
parameter S1 = 'd1;
parameter S2 = 'd2;
parameter S3 = 'd3;
reg [1:0] state;
always@(posedge clk or negedge rst)
if(!rst)
state <= S0;
else
case(state)
S0:state <= S1;
S1:state <= S2;
S2:state <= S3;
S3:state <= S0;
endcase
always@(*)
if(state == S1)
clk_out <= 'd1;
else
clk_out <= 'd0;
//*************code***********//
endmodule
是否也可以使用移位
得到状态。`timescale 1ns/1ns
module huawei7(
input wire clk ,
input wire rst ,
output reg clk_out
);
//*************code***********//
parameter S0 = 4'b0001;
parameter S1 = 4'b0010;
parameter S2 = 4'b0100;
parameter S3 = 4'b1000;
reg [3:0] state;
always@(posedge clk or negedge rst)
if(!rst)
state <= S0;
else
state <= state << 1;
always@(*)
if(state == S1)
clk_out <= 'd1;
else
clk_out <= 'd0;
//*************code***********//
endmodule
`timescale 1ns/1ns
module huawei7(
input wire clk ,
input wire rst ,
output reg clk_out
);
//*************code***********//
reg [1:0] state;
always@(posedge clk or negedge rst)
if(!rst)
state <= 'd0;
else
state <= state + 1'b1;
always@(*)
if(state == 2'b01)
clk_out <= 'd1;
else
clk_out <= 'd0;
//*************code***********//
endmodule
描述
题目描述:
求两个四位的数据编写一个四位的超前进位加法器,建议使用子模块
提示:超前进位加法器的位公式如下
这里‘+’ ‘·’符号不是‘加’和‘乘’,是‘或’和 ‘与’
波形示意图:
输入描述:
A B 输入值
输出描述:
OUT 加法结果
`timescale 1ns/1ns
module counter_16(
input clk ,
input rst_n ,
output reg [3:0] Q
);
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
Q <= 'd0;
else
Q <= Q + 1'b1;
end
endmodule
`timescale 1ns/1ns
/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
parameter WIDTH = 8)(
input wclk
,input wenc
,input [$clog2(DEPTH)-1:0] waddr
,input [WIDTH-1:0] wdata
,input rclk
,input renc
,input [$clog2(DEPTH)-1:0] raddr
,output reg [WIDTH-1:0] rdata
);
reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];
always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end
always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end
endmodule
/**********************************SFIFO************************************/
module sfifo#(
parameter WIDTH = 8,
parameter DEPTH = 16
)(
input clk ,
input rst_n ,
input winc ,
input rinc ,
input [WIDTH-1:0] wdata ,
output reg wfull ,
output reg rempty ,
output wire [WIDTH-1:0] rdata
);
localparam ADDR_WIDTH = $clog2(DEPTH) - 1 + 1;
//通过深度换算出需要多少位宽,因为fifo在最高位需要一个标志位产生满信号,上述再+1
//第二步:给RAM申明缺少的端口信号
///
reg [ADDR_WIDTH:0] waddr,raddr;//写地址,读地址
wire wenc,renc;//写使能信号,读使能信号
//第三步:写地址操作,什么时候写
///
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
waddr <= 'd0;
end
else begin
if(wenc) begin
waddr <= waddr + 1'b1;
end
else begin
waddr <= waddr;
end
end
end
assign wenc = winc && ~wfull;//写使能信号
//第四步:读地址操作,什么时候读
///
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
raddr <= 'd0;
end
else begin
if(renc) begin
raddr <= raddr + 1'b1;
end
else begin
raddr <= raddr;
end
end
end
assign renc = rinc && ~rempty;//读使能信号
//第五步:产生空满信号
///
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
wfull <= 'd0;
rempty <= 'd0;
end
else begin
wfull <= ((waddr[ADDR_WIDTH] != raddr[ADDR_WIDTH]) && (waddr[ADDR_WIDTH-1:0] == raddr[ADDR_WIDTH-1:0]));
rempty <= raddr == waddr;
end
end
//第一步:例化双口RAM
///
dual_port_RAM
#(
.DEPTH(DEPTH)
,.WIDTH(WIDTH)
)
dual_port_RAM_inst
(
.wclk (clk )
,.wenc (wenc )
,.waddr (waddr ) //深度对2取对数,得到地址的位宽。
,.wdata (wdata ) //数据写入
,.rclk (clk )
,.renc (renc )
,.raddr (raddr ) //深度对2取对数,得到地址的位宽。
,.rdata (rdata ) //数据输出
);
endmodule
`timescale 1ns/1ns
module det_moore(
input clk ,
input rst_n ,
input din ,
output reg Y
);
reg [3:0] din_reg;
always@(posedge clk or negedge rst_n)
if(!rst_n)
din_reg <= 'd0;
else
din_reg <= {din_reg,din};
always@(posedge clk or negedge rst_n)
if(!rst_n)
Y <= 'd0;
else
Y <= din_reg == 4'b1101;
endmodule
`timescale 1ns/1ns
module add_half(
input A ,
input B ,
output wire S ,
output wire C
);
assign S = A ^ B;
assign C = A & B;
endmodule
/***************************************************************/
module add_full(
input A ,
input B ,
input Ci ,
output wire S ,
output wire Co
);
wire [1:0] s,c;
add_half add_half_U1(A,B,s[0],c[0]);
add_half add_half_u2(Ci,s[0],s[1],c[1]);
assign S = s[1];
assign Co = |c;
endmodule
半加器是不考虑进位的
,但是很多人肯定会想到,好像是有进位的,就比如1'b1+1'b1 = 2'b10
.注意了,此处的进位指的是,在1'b1+1'b1
时考虑低位的进位吗?没有!半加器没有接收进位的输入端
,全加器有进位输入端,在将两个多位二进制数相加时,除了最低位外,每一位都要考虑来自低位的进位,半加器则不用考虑,只需要考虑两个输入端相加即可。半加器
是实现两个一位二进制数加法运算的器件。它具有两个输入端(被加数A和加数B)及输出端Y。全加器
是用门电路实现两个二进制数相加并求出和的组合线路,称为一位全加器。一位全加器可以处理低位进位,并输出本位加法进位。多个一位全加器进行级联可以得到多位全加器。描述
② 请用全加器电路①实现串行进位的4位全加器电路
1位全加器参考代码如下:
module add_half(
input A ,
input B ,
output wire S ,
output wire C
);
assign S = A ^ B;
assign C = A & B;
endmodule
/***************************************************************/
module add_full(
input A ,
input B ,
input Ci ,
output wire S ,
output wire Co
);
wire c_1;
wire c_2;
wire sum_1;
add_half add_half_1(
.A (A),
.B (B),
.S (sum_1),
.C (c_1)
);
add_half add_half_2(
.A (sum_1),
.B (Ci),
.S (S),
.C (c_2)
);
assign Co = c_1 | c_2;
endmodule
输入描述:
input [3:0] A ,
input [3:0] B ,
input Ci ,
输出描述:
output wire [3:0] S ,
output wire Co
`timescale 1ns/1ns
module add_4(
input [3:0] A ,
input [3:0] B ,
input Ci ,
output wire [3:0] S ,
output wire Co
);
// assign {Co,S} = A + B + Ci;
wire C[3:0];
generate
genvar i ;
for(i=0;i<=3;i=i+1)
begin: Li
if(i==0) begin
add_full add_full_li(
.A(A[i]),
.B(B[i]),
.Ci(Ci),
.S(S[i]),
.Co(C[i]));
end
else begin
add_full add_full_li(
.A(A[i]),
.B(B[i]),
.Ci(C[i-1]),
.S(S[i]),
.Co(C[i]));
end
end
endgenerate
assign Co = C[3];
endmodule
module add_half(
input A ,
input B ,
output wire S ,
output wire C
);
assign S = A ^ B;
assign C = A & B;
endmodule
/***************************************************************/
module add_full(
input A ,
input B ,
input Ci ,
output wire S ,
output wire Co
);
wire c_1;
wire c_2;
wire sum_1;
add_half add_half_1(
.A (A),
.B (B),
.S (sum_1),
.C (c_1)
);
add_half add_half_2(
.A (sum_1),
.B (Ci),
.S (S),
.C (c_2)
);
assign Co = c_1 | c_2;
endmodule
`timescale 1ns/1ns
module add_4(
input [3:0] A ,
input [3:0] B ,
input Ci ,
output wire [3:0] S ,
output wire Co
);
// assign {Co,S} = A + B + Ci;
wire C[3:0];
generate
genvar i ;
for(i=0;i<=3;i=i+1)
begin: Li
if(i==0) begin
add_full add_full_li(
.A(A[i]),
.B(B[i]),
.Ci(Ci),
.S(S[i]),
.Co(C[i]));
end
else begin
add_full add_full_li(
.A(A[i]),
.B(B[i]),
.Ci(C[i-1]),
.S(S[i]),
.Co(C[i]));
end
end
endgenerate
assign Co = C[3];
endmodule
module add_full(
input A,
input B,
input Ci,
output S,
output Co
);
assign S = A^B^Ci;
assign Co = ((A^B)&Ci)|(A&B);
endmodule
`timescale 1ns/1ns
module ali16(
input wire clk,
input wire rst_n,
input wire d,
output reg dout
);
reg rst0,rst1;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
{rst0,rst1} <= 'd0;
end
else begin
{rst0,rst1} <= {1'b1,rst0};
end
end
always @ (posedge clk or negedge rst1)begin
if(!rst1) begin
dout <= 1'b0;
end
else begin
dout <= d;
end
end
endmodule
推荐相关文章