USTC Verilog OJ 重点题目题解

发布于:2022-12-30 ⋅ 阅读:(278) ⋅ 点赞:(0)

 

1,在前面的电路中,寄存器输出端 q 在每个时钟的上升沿都会更新一次,但有时候我们可能需要使输出端保持不变,这时就需要加入使能信号,创建一 16bit 位宽(2byte)的寄存器,其中每字节都由一个使能信号控制,使能为 0 时,输出保持不变,使能为 1 时更新 q。时钟上升沿触发,同步复位,复位低电平有效,复位值为 0。

module top_module(
  input clk,
  input resetn,
  input [1:0] byteena,
  input [15:0] d,
  output reg [15:0] q

);
  // Write your code here
    always@(posedge clk)
        begin
            if(~resetn)
                q <= 0;
            else
                case(byteena)
                    2'b11:q <= d;
                    2'b10:q[15:8] <= d[15:8];
                    2'b01:q[7:0] <= d[7:0];
                    default:q <= q;
                endcase
        end
                                     
        
endmodule

2,编写Verilog代码,实现下图所示的电路功能,假设所有D触发器的初始复位值为0

module top_module (
    input clk,
    input x,
    output z
);
    reg q1,q2,q3;
    initial
            begin
                q1 = 0;
                q2 = 0;
                q3 =0;
            end
    always@(posedge clk)
        begin
            q1 <= q1 ^ x;
            q2 <= (~q2) & x;
            q3 <= (~q3) | x;
            
        end
    assign z = ~(q1 ^ q2 ^ q3);

endmodule

3,在实际应用中,我们经常需要对某个信号的边沿进行检测,并以此作为后续动作的触发信号(例如电脑键盘的某个按键被按下或者被松开,在电路中则对应的是电平的变化)。
设计一个电路,包含clk信号、1bit输入信号in和1bit输出信号out,当in信号从0变为1时(相对于clk,该信号变化频率很慢),out信号在in信号上升沿附近输出1个时钟周期的高电平脉冲,其余时刻都为0

module top_module (
    input clk,
    input in,
    output out
);
	reg q1,q2;
    assign out = q1 & ~q2;
    initial
        begin
            q1 = 0;
            q2 = 0;
        end
   
    always@(posedge clk)
        begin
            q2 <= q1;
            q1 <= in;
        end
   
endmodule

4,根据上升沿检测的思路,设计一双边沿检测电路,即在输入信号的上升沿和下降沿附近时刻,各输出一个高电平脉冲,如下图所示

module top_module (
    input clk,
    input in,
    output out
);
	reg q1,q2;
    
    always@(posedge clk)
        begin
            q2 <= q1;
            q1 <= in;
        end
    assign out = (q1 & ~q2)|(~q1 & q2);
  
endmodule

5,构建一个4位移位寄存器(右移),具有异步复位、同步加载和启用功能。

areset:将移位寄存器重置为零。
load:用数据[3:0]加载移位寄存器,而不是移位。
ena:右移(q[3]变为零,q[0]移出并消失)。
q:移位寄存器的内容。
* 如果load和ena输入同时有效,则load输入具有更高的优先级。

module top_module(
    input clk,
    input areset,  //异步、高有效、复位值为0
    input load,
    input ena,
    input [3:0] data,
    output reg [3:0] q); 
//Write your code here
    reg [1:0]s;
    
    always@(posedge clk or negedge areset)
        begin
            s <= {load,ena};
            if(areset)
                q <= 0;
            else
                case(s)
                    2'b11:q <= data;
                    2'b10:q <= data;
                    default:q[3:0] <= {1'b0,q[3:1]};
                    
                endcase
        end
                    
                    
endmodule
module top_module(
    input clk,
    input areset,  // async active-high reset to zero
    input load,
    input ena,
    input [3:0] data,
    output reg [3:0] q
); 
    always @ (posedge clk or posedge areset)begin
        if(areset)begin
            q <= 4'b0;
        end
        else if(load)begin
            q <= data;
        end
        else if(ena)begin
            q <= {1'b0,q[3:1]};
        end
        else
            q <= q;
    end

endmodule

第一段代码会延迟一个时钟周期,想一想为什么

 6,创建一带有使能信号的递减计数器,当使能信号有效(高电平)时,从15到5循环递减计数,每个周期减1,使能信号无效时,计数值保持不变,电路采用同步复位方式,高电平有效,复位值为5

module top_module(
    input clk,
    input reset,
    input en,
  	output reg [3:0]q);
    always@(posedge clk)
        begin
            if(reset)
                q <= 4'b0101;
            else
                if(en)
                    if(q <= 4'b0101)
                        q <= 4'b1111;
            		else
                        q <= q - 1;
        end
endmodule

7,下图是摩尔型有限状态机的结构图,我们可以发现其包含三个部分,第一部分为纯组合逻辑,通过现态和输入信号生成次态信号,第二部分为时序逻辑,该时序逻辑非常简单,只包含一个带有复位功能的寄存器单元,复位时现态信号变为初始值,否则在每个时钟的上升沿将次态信号赋值给现态信号。第三部分为组合逻辑,该部分通过现态信号生成各输出信号。

module top_module(
    input clk,
    input areset,    
    input in,
    output out); 
    parameter A=1'b0, B=1'b1; 
	reg state, next_state;
    always @(*) 
        begin   
       	if(in)
            next_state = state;
        else
            begin
                case(state)
                        A:next_state = B;
                        B:next_state = A;
                        default:next_state = B;
                endcase
            end
	end
	always @(posedge clk, posedge areset) 
        begin   
        if(areset)
            state <= B;
        else
            state <= next_state;    
    end
    assign out = (state == B)? 1'b1 : 1'b0;
endmodule

8,给定被测试模块dut,其verilog代码如下:

module dut(input clk, output reg [2:0]out);
  //测试模块
  always @(posedge clk)
    out <= out + 1'b1;  
endmodule

请编写仿真文件,对该模块进行仿真(dut模块可直接调用,不需要用户编写),clk信号应符合以下波形:

module tb();
wire [2:0]out;//必要输出信号 	
	//信号定义
reg clk;
parameter clk_period = 10;
	//信号生成
initial begin
    clk = 0;
    forever
        #(clk_period/2) clk = ~clk; 
end
	//模块例化
    dut dut1(clk,out);
endmodule

module dut(input clk, output reg [2:0]out);
  //测试模块
  always @(posedge clk)
    out <= out + 1'b1;  
endmodule

9,在RV32I中,寄存器堆指32个通用寄存器的集合,具有专门的读写端口,可并发访问不同寄存器

module top_module(
input         clk,
input  [4:0]  A1,A2,A3,
input  [31:0] WD,
input 	      WE,
output [31:0] RD1,RD2
);
reg [31:0] reg_file[0:31];
//初始化寄存器堆
integer i;
initial
begin
    for(i=0;i<32;i=i+1) reg_file[i] = 0;
end

//写入寄存器
always@(posedge clk)
begin
    if(WE&A3!=5'd0)
        reg_file[A3] <= WD;
        
end

//读取寄存器
    assign RD1 = reg_file[A1];
    assign RD2 = reg_file[A2];

endmodule

这里注意第0个寄存器为只读寄存器。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到