硬件语言Verilog HDL牛客刷题 day09 哲K部分

1.VL59 根据RTL图编写Verilog程序

1.题目:

根据以下RTL图,使用 Verilog HDL语言编写代码,实现相同的功能,并编写testbench验证功能

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第1张图片

 硬件语言Verilog HDL牛客刷题 day09 哲K部分_第2张图片


2.解题思路

        2.1 了解D触发器的知识 (在时钟是上升沿的时候, 输入是什么输出什么)

        2.2 注意经过D触发器的器件需要 延时一个周期。

        链接:时序约束系列之D触发器原理和FPGA时序结构 - 知乎 (zhihu.com) 


3.解题代码

        

`timescale 1ns/1ns

module RTL(
	input clk,
	input rst_n,
	input data_in,
	output reg data_out
	);
reg flag;
always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				flag<=0;
			end
		else
			begin
				flag <=data_in ;
			end
	end

always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				data_out<=0;
			end
		else
			begin
				data_out <= ~flag && data_in ;
			end
	end




endmodule


2.VL60 使用握手信号实现跨时钟域数据传输

1.题目:

分别编写一个数据发送模块和一个数据接收模块,模块的时钟信号分别为clk_a,clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7,在每个数据传输完成之后,间隔5个时钟,发送下一个数据。请在两个模块之间添加必要的握手信号,保证数据传输不丢失。
    模块的接口信号图如下:

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第3张图片

data_req和data_ack的作用说明:
data_req表示数据请求接受信号。当data_out发出时,该信号拉高,在确认数据被成功接收之前,保持为高,期间data应该保持不变,等待接收端接收数据。
当数据接收端检测到data_req为高,表示该时刻的信号data有效,保存数据,并拉高data_ack。
当数据发送端检测到data_ack,表示上一个发送的数据已经被接收。撤销data_req,然后可以改变数据data。等到下次发送时,再一次拉高data_req。 

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第4张图片

 


2.解题思路

        2.1 两个部分一个接收端, 一个发送端。

        2.2  两个部分的需求分析硬件语言Verilog HDL牛客刷题 day09 哲K部分_第5张图片

         2.3 开始   使用计时器 启动 发送部分的 data_req 信号。

         2.4 信号需要延时两个周期。

  


3.解题代码

`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_r1, data_ack_r2;
    reg [2:0] cnt;
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
        begin
            data_ack_r1 <= 1'b0;
            data_ack_r2 <= 1'b0;
        end
        else
        begin
            data_ack_r1 <= data_ack;
            data_ack_r2 <= data_ack_r1;
        end
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            data <= 4'b0;
        else if(data_ack_r1 && !data_ack_r2)
            data <= data + 1'b1;
        else
            data <= data;
    
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            cnt <= 1'b0;
        else if (data_ack_r1 && !data_ack_r2)
            cnt <= 1'b0;
        else if (data_req)  //正在请求时不计数
            cnt <= cnt;
        else 
            cnt <= cnt + 1'b1;
             
    always @ (posedge clk_a or negedge rst_n)
        if (!rst_n) 
            data_req <= 1'b0;
        else if (cnt == 3'd4)  
            data_req <= 1'b1;
        else if (data_ack_r1 && !data_ack_r2)
            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_1, data_req_2;
    
    always @ (posedge clk_b or negedge rst_n)
        if (!rst_n) begin
            data_req_1 <= 1'b0;
            data_req_2 <= 1'b0;
        end
        else begin
            data_req_1 <= data_req;
            data_req_2 <= data_req_1;
        end
 
    always @ (posedge clk_b or negedge rst_n)
        if (!rst_n) begin
            data_ack <= 1'b0;
            data_in_reg <= 4'b0;
        end
        else if (data_req_1 && !data_req_2) begin
            data_ack <= 1'b1;
            data_in_reg <= data;
        end
        else begin 
            data_ack <= 1'b0;
            data_in_reg <= data_in_reg; 
        end
    
endmodule


3. VL61 自动售卖机

1. 题目

请设计状态机电路,实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。

电路的接口如下图所示。sel信号会先于din信号有效,且在购买一种饮料时值不变。

  • sel为选择信号,用来选择购买饮料的种类,sel=0,表示购买A饮料,sel=1,表示购买B饮料;
  • din表示投币输入,din=0表示未投币,din=1表示投币5元,din=2表示投币10元,不会出现din=3的情况;
  • drinks_out表示饮料输出,drinks_out=0表示没有饮料输出,drinks_out=1表示输出A饮料,drinks_out=2表示输出B饮料,不出现drinks_out =3的情况,输出有效仅保持一个时钟周期;
  • change_out表示找零输出,change_out=0表示没有找零,change_out=1表示找零5元,输出有效仅保持一个时钟周期。

接口电路图如下:

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第6张图片

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第7张图片


2.解题思路

        2.1 首先 注意这个题有一点细节, 在买 B 饮料的时候, 可以存钱。(我去他的)。

                2.1.1 在第一次 5 元 存入 , 第二次 5元 输出饮料。零钱清零。

                2.1.2 在第一次 5元 存入 , 第二次  10元 输出饮料。 零钱输出 5 元。

        2.1 信号延时 1 个周期输出。 (这是这个周期是 符合条件, 下一个 周期输出信号)。


3.解题代码

`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 money;

always@(posedge clk or negedge rst_n)
    begin
        if(~rst_n)
            begin
                drinks_out <=0;
                change_out <=0;
                money <=0;
            end
        else
            begin
                if(sel == 1'b1)
                    begin
                        if(din == 2'd1)//题目没有说可以存钱啊!1
                            begin
                                drinks_out <=0;
                                change_out <=1'd0; //连续输入两次5 元也可以
                                money <=1;
                                if(money)
                                    begin
                                        drinks_out <=2'd2;
                                        change_out <=1'd0;
                                        money <=0;
                                    end
                            end
                        else if(din == 2'd2)
                            begin
                                drinks_out <=2'd2;
                                change_out <=0;
                                 if(money)
                                    begin
                                        drinks_out <=2'd2;
                                        change_out <=1'd1;
                                        money <=0;
                                    end
                            end
                        else
                            begin
                                drinks_out <=0;
                                change_out <=0;
                            end
                    end
                else if(sel == 1'b0)
                    begin
                        if(din == 2'd1)
                            begin
                                drinks_out <=2'd1;
                                change_out <=1'd0;
                            end
                        else if(din == 2'd2)
                            begin
                                drinks_out <=2'd1;
                                change_out <=1'd1;
                            end
                         else
                            begin
                                drinks_out <=0;
                                change_out <=0;
                            end
                    end
            end
    end



endmodule


4.VL62 序列发生器

1.题目:

       编写一个模块,实现循环输出序列001011。

模块的接口信号图如下:

硬件语言Verilog HDL牛客刷题 day09 哲K部分_第8张图片


2. 解题思路

        2.1 第一种设置  参数  flag 001011 直接左移  输出  flag[5 ].

        2.2 设置标志位 对应输出。

        2.3 注意信号延时一个 周期。


3.解题代码

`timescale 1ns/1ns

module sequence_generator(
	input clk,
	input rst_n,
	output reg data
	);

parameter s0 = 3'd0;
parameter s1 = 3'd1;
parameter s2 = 3'd2;
parameter s3 = 3'd3;
parameter s4 = 3'd4;
parameter s5 = 3'd5;
reg[2:0] flag;
//需要延后一个周期 与
always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				flag <= s0;	
			end
		else
			begin
				case(flag)
					s0 : flag <=s1;
					s1 : flag <=s2;
					s2 : flag <=s3;
					s3 : flag <=s4;
					s4 : flag <=s5;
					s5 : flag <=s0;
					default:flag <=s0;
				endcase
			end
	end

always@(posedge clk or negedge rst_n)
	begin
		if(~rst_n)
			begin
				data <=0;
			end
		else
			begin
				case (flag)
					s0: data <= 0;
					s1: data <= 0;
					s2: data <= 1;
					s3: data <= 0;
					s4: data <= 1;
					s5: data <= 1;
				endcase
			end
	end



endmodule

 

你可能感兴趣的:(牛客刷题,Verilog,HDL,fpga开发)