USTC Verilog OJ Solutions

科大OJ

其对应的英文版:HDLBits刷题网站

01输出1

module top_module(output one);
    assign one = 1;
endmodule

02输出0

module top_module(
    output zero
);// Module body starts after semicolon
    assign zero = 0;
endmodule

03wire

module top_module(input in, output out);
    assign out = in;
endmodule

04多个端口的模块

module top_module(
    input a, b, c,
    output w, x, y, z
);
    assign w=a;
    assign x=b;
    assign y=b;
    assign z=c;
endmodule

05非门

module top_module(
    input in,
    output out
);
    assign out=~in;
endmodule

06与门

module top_module(
    input a, b,
    output out
);
    assign out=a & b;
endmodule

07或非门

module top_module(
    input a, b,
    output out
);
    assign out=!(a | b);
endmodule

08同或门

module top_module(
    input a, b,
    output out
);
    assign out = !(a ^ b);
endmodule

09线网型中间信号

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out,
    output out_n   
); 
// 请用户在下方编辑代码
	wire a_and_b, c_and_d, or_out;
    assign a_and_b = a&b;
    assign c_and_d = c&d;
    assign or_out = a_and_b | c_and_d;
    assign out = or_out;
    assign out_n = ~or_out;
//用户编辑到此为止
endmodule

10向量

module top_module ( 
    input wire [2:0] vec,
    output wire [2:0] outv,
    output wire o2,
    output wire o1,
    output wire o0);
// Module body starts after module declaration
// 请用户在下方编辑代码
    assign outv[2:0] = vec[2:0];
    assign o0 = vec[0];
    assign o1 = vec[1];
    assign o2 = vec[2];
// 用户编辑到此为止
endmodule

11向量_续1

`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
module top_module( 
    input	wire	[15:0]	in,
    output	wire	[7:0]	out_hi,
    output	wire	[7:0]	out_lo 
);
	// Write your code here
    assign out_hi = in[15:8];
    assign out_lo = in[7:0];
endmodule

12向量_续2

module top_module(
  input [31:0] in,
  output [31:0] out
);
    assign out[31:24] = in[7:0];
    assign out[23:16] = in[15:8];
    assign out[15:8] = in[23:16];
    assign out[7:0] = in[31:24];
endmodule

13位操作

module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);
  // Write your code here
    assign out_not[5:0] = ~({b[2:0],a[2:0]});
    assign out_or_bitwise = a | b;
    assign out_or_logical = a[0]|a[1]|a[2]|b[0]|b[1]|b[2];
    
endmodule

14位操作

module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
    /*
    assign out_and = in[0]&in[1]&in[2]&in[3];
    assign out_or = in[0]|in[1]|in[2]|in[3];
    assign out_xor = in[0]^in[1]^in[2]^in[3];
    */
    assign out_and = &in[2:0];
    assign out_or = |in[2:0];
    assign out_xor = ^in[2:0];
    
endmodule

15向量拼接

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );
    // assign { ... } = { ... };
    assign {w, x, y, z} = {a, b, c, d, e, f, 2'b11};
endmodule

16向量翻转

module top_module( 
    input [7:0] in,
    output [7:0] out
);
    assign out = {in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7]};
endmodule

17复制算子

module top_module (
    input [7:0] in,
    output [31:0] out );//
    assign out = {{24{in[7]}},in[7:0]};
endmodule

18复制算子_2

module top_module (
    input a, b, c, d, e,
    output [24:0] out );//
    // The output is XNOR of two vectors created by 
    // concatenating and replicating the five inputs.
    assign out = ~({ {5{a}}, {5{b}},{5{c}},{5{d}}, {5{e}}} ^ { 5{a, b, c, d, e} });
endmodule

19模块例化

module top_module(
  input 	a,
  input 	b,
  output 	out
);
  
// 请用户在下方编辑代码
    mod_a imod_a1(
        .in1(a),
        .in2(b),
        .out(out)
    );
//用户编辑到此为止
endmodule

module mod_a ( 
  input 	in1, 
  input 	in2, 
  output 	out 
);
assign out = in1 & in2;
endmodule

20基于端口位置的实例化

module mod_a(
	output out1, out2,
	input in1,in2,in3,in4);
	assign out1 = in1 & in2 & in3 & in4; 	//这只是一个简单的示例
	assign out2 = in1 | in2 | in3 | in4;	//这只是一个简单的示例
endmodule

module top_module( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
// 请用户在下方编辑代码
mod_a imod_a1(out1, out2, a, b, c, d);
// 用户编辑到此为止
endmodule

21基于端口名称的实例化

module mod_a (
    output   out1	,
    output   out2	,
    input    in1	,
    input    in2	,
    input    in3	,
    input    in4
);
    assign out1 = in1 & in2 & in3 & in4;    //这只是一个简单的示例
    assign out2 = in1 | in2 | in3 | in4;    //这只是一个简单的示例
endmodule

module top_module ( 
	input	a	,
    input	b	,
    input	c	,
    input	d	,
    output	out1,
    output	out2
);
	//Write your code here
    mod_a imod_a1(
        .out1(out1),
        .out2(out2),
        .in1(a),
        .in2(b),
        .in3(c),
        .in4(d)
    );
endmodule

22多个模块的例化

module my_dff(input clk,input d,output reg q);
	always@(posedge clk)
    	q <= d;
endmodule

module top_module ( input clk, input d, output q );
 // Write your code here
    wire t1, t2;
    my_dff idff1(clk, d, t1);
    my_dff idff2(clk, t1, t2);
    my_dff idff3(clk, t2, q);
endmodule

23模块与向量信号

module my_dff8(
  input clk,
  input [7:0] d,
  output reg [7:0] q
);
	always@(posedge clk)
    	q <= d;
endmodule

module top_module(
  input clk,
  input [7:0] d,
  input [1:0] sel,
  output reg [7:0] q
);
  // Write your code here
    wire [7:0]t1;
    wire [7:0]t2;
    wire [7:0]t3;
    my_dff8 idff8_1(clk, d, t1);
    my_dff8 idff8_2(clk, t1, t2);
    my_dff8 idff8_3(clk, t2, t3);
    
    always @(*) begin
        case(sel)
            2'd0: q <= d;
        	2'd1: q <= t1;
        	2'd2: q <= t2;
        	2'd3: q <= t3;
        endcase
    end       
endmodule

24加法器

module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
	assign {cout,sum} = a + b + cin;
endmodule

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
  wire c;
    add16 iadd16_1(.a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(c));
    add16 iadd16_2(.a(a[31:16]), .b(b[31:16]), .cin(c), .sum(sum[31:16]), .cout());
endmodule

25多层次例化加法器

module add1 ( input a, input b, input cin,   output sum, output cout );
// Full adder module here
    assign sum = a ^ b ^ cin;
    assign cout = (a&b)|(a&cin)|(b&cin);
endmodule

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum    
);//
    wire c;
    add16 a0(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(c));
    add16 a1(.a(a[31:16]), .b(b[31:16]), .cin(c), .sum(sum[31:16]), .cout());
endmodule

26进位选择加法器

module add16 ( 
	input[15:0] a, 
    input[15:0] b, 
    input cin, 
    output[15:0] sum, 
    output cout 
);
	assign {cout,sum} = a + b + cin;
endmodule

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire [15:0]sum_0;
    wire [15:0]sum_1;
    wire c;
    add16 iadd16_high_0(.a(a[31:16]), .b(b[31:16]), .cin(0), .sum(sum_0), .cout());
    add16 iadd16_high_1(.a(a[31:16]), .b(b[31:16]), .cin(1), .sum(sum_1), .cout());
    add16 iadd16_low(.a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(c));
assign sum[31:16] = (c == 1 ? sum_1 : sum_0);

endmodule

27加法减法器

module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
	assign {cout,sum} = a + b + cin;
endmodule

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    
   wire [31:0]b2 = b ^ {32{sub}};
    wire c;
    add16 iadd16_1(.a(a[15:0]), .b(b2[15:0]), .cin(sub), .sum(sum[15:0]), .cout(c));
    add16 iadd16_2(.a(a[31:16]), .b(b2[31:16]), .cin(c), .sum(sum[31:16]), .cout());
endmodule

28always过程块_组合逻辑

module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
    assign out_assign = a & b;
    always @(*) begin
        out_alwaysblock <= a & b;
    end

endmodule

29always过程块_时序逻辑

module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   
);
// 请用户在下方编辑代码
assign out_assign = a ^ b;
    //reg不一定非要在电路中引入寄存器
    always @(*) begin
        out_always_comb = a ^ b;
    end
    
    always @(posedge clk) begin
        out_always_ff <= a ^ b;
    end
    
//用户编辑到此为止
endmodule

30ifelse语句

module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always); 
// 请用户在下方编辑代码
    wire [1:0]sel = {sel_b1, sel_b2};
    assign out_assign = (sel == 3 ? b : a);
    always @(*) begin
        if(sel == 3) out_always = b;
        else out_always = a;
    end
//用户编辑到此为止
endmodule

31if语句与锁存器

module top_module (
    input		cpu_overheated		,
    output	reg	shut_off_computer	,
    input      	arrived				,
    input      	gas_tank_empty		,
    output 	reg keep_driving
);
  	// Edit the code below
	always @(*) begin
    	if (cpu_overheated)
        	shut_off_computer = 1'b1;
        else
            shut_off_computer = 1'b0;
    end

    always @(*) begin
    	if (~arrived)
        	keep_driving = ~gas_tank_empty;
        else
            keep_driving = 0;
    end
endmodule

32case语句

module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );//
    always@(*) begin  // This is a combinational circuit
        case(sel)
            0: out = data0;
            1: out = data1;
            2: out = data2;
            3: out = data3;
            4: out = data4;
            5: out = data5;
        	default: out = 3'b0;
        endcase
    end
endmodule

33优先编码器

module top_module(
  input [3:0] in,
  output reg [1:0] pos
);
  // Write your code here
    always @(*) begin
        case(in)
            4'b0000: pos = 0;
            4'b0001: pos = 0;
            4'b0010: pos = 1;
            4'b0011: pos = 0;
            4'b0100: pos = 2;
            4'b0101: pos = 0;
            4'b0110: pos = 1;
			4'b0111: pos = 0;
            4'b1000: pos = 3;
            4'b1001: pos = 0;
            4'b1010: pos = 1;
            4'b1011: pos = 0;
            4'b1100: pos = 2;
            4'b1101: pos = 0;
            4'b1110: pos = 1;
            4'b1111: pos = 0;
        endcase
    end
endmodule

34casez语句

module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    
    always @(*) begin
        casez(in)
            8'bzzzz_zzz1: pos = 0;
            8'bzzzz_zz1z: pos = 1;
            8'bzzzz_z1zz: pos = 2;
            8'bzzzz_1zzz: pos = 3;
            8'bzzz1_zzzz: pos = 4;
            8'bzz1z_zzzz: pos = 5;
            8'bz1zz_zzzz: pos = 6;
            8'b1zzz_zzzz: pos = 7;
            default: pos = 0;
        endcase
    end

endmodule

35避免锁存器

module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 

    always @(*) begin
            up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
        case(scancode)
            16'he06b: left = 1;
            16'he072: down = 1;            
            16'he074: right = 1;
            16'he075: up = 1;
        endcase
    end
endmodule

36条件运算符

module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);
    
    wire [7:0] min_ab = a < b ? a : b;
    wire [7:0] min_cd = c < d ? c : d;
    assign min = min_ab < min_cd ? min_ab : min_cd;
endmodule

37归约运算符

module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^in[7:0];

endmodule

38D触发器

module top_module (
    input clk,    // Clocks are used in sequential circuits
    input d,
    output reg q );//
    // Use a clocked always block
    //   copy d to q at every positive edge of clk
    //   Clocked always blocks should use non-blocking assignments
    always @(posedge clk) begin
        q <= d;
    end
endmodule

39寄存器

module top_module (
    input 				clk,
    input [7:0] 		d,
    output reg [7:0] 	q
);
// 请用户在下方编辑代码

    always @(posedge clk) begin
        q <= d;
    end

//用户编辑到此为止
endmodule

40有复位功能的寄存器

module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output reg [7:0] q
);
    always @(posedge clk) begin
        if (reset) q <= 8'b0;
        else q <= d;
    end

endmodule

41下降沿触发的寄存器

module top_module (
    input				clk		,
    input				reset	,
    input		[7:0]	d		,
    output	reg	[7:0]	q
);
	// Write your code here
    always @(negedge clk) begin
        if(reset) q <= 8'h34;
        else q <= d;
    end
endmodule

42异步复位的寄存器

module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output reg [7:0] q
);
// Write your code here
    always @(posedge clk or posedge areset) begin
        if (areset) q <= 8'b0;
        else q <= d;
    end
endmodule

43带使能的寄存器

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 <= 16'b0;
        else begin
            q[15:8] <= byteena[1] == 1 ? d[15:8] : q[15:8];
            q[7:0] <= byteena[0] == 1 ? d[7:0] : q[7:0];   
        end
    end
endmodule

44触发器+逻辑门

module top_module (
    input clk,
    input in, 
    output reg out);
    
    wire d = out ^ in;
    always @(posedge clk) begin
        out <= d;
    end        

endmodule

45寄存器+逻辑门

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

endmodule

46上升沿检测

module top_module (
    input clk,
    input in,
    output reg out = 0
);
    wire prev_in;
    dff idff_1(.clk(clk), .d(in), .q(prev_in));
    always @(posedge clk) begin
        if(~prev_in & in) out <= 1;
        else out <= 0;
    end
endmodule
            
module dff(
    input clk,
	input d,
	output reg q
);
    initial q = 0;
    always @(posedge clk) begin
        q <= d;
    end
                
endmodule

47双边沿检测

module top_module (
    input clk,
    input in,
    output reg out
);
    //initial out = 0;
    wire prev_in;
    dff idff_1(.clk(clk), .d(in), .q(prev_in));
    always @(posedge clk) begin
		out <= prev_in ^ in;
    end

endmodule

module dff (
    input clk,
    input d,
    output reg q
);
    always @(posedge clk) begin
        q <= d;
    end
endmodule

48计数器

module top_module (
    input clk,
    input reset,      // 异步复位,高电平有效,复位值为0
    output reg [3:0] q);
    
    always @(posedge clk or posedge reset) begin
        if(reset) q <= 0;
        else if(q == 15) q <= 0;
        else q <= q + 1;
    end

endmodule

49十进制计数器

module top_module (
    input 				clk		,	//时钟信号
    input 				reset	,   //同步高电平有效复位信号
    output reg 	[3:0] 	q			//计数结果
);
// 请用户在下方编辑代码
    always @(posedge clk) begin
        if(reset) q <= 1;
        else if(q == 10) q <= 1;
        else q <= q + 1;        
    end
//用户编辑到此为止 
endmodule

50带使能的计数器

module top_module(
    input clk,
    input reset,
    input en,
  	output reg [3:0]q);
    
    always @(posedge clk) begin
        if(reset) q <= 5;
        else if (~en) q <= q;
        else if (q == 5) q <= 15;
        else q <= q - 1;        
    end

endmodule

51秒表

module top_module(
    input 			clk		,  //4Hz
    input 			reset	,
	output	[7:0]	ss
); 
	// Write your code here
    reg [1:0]cnt;
    reg [3:0]ones_place;
    reg [3:0]tens_place;
    //initial begin cnt = 0; ones_place = 0; tens_place = 0;end
    assign ss[3:0] = ones_place[3:0];
    assign ss[7:4] = tens_place[3:0];
    
    always @(posedge clk) begin
        if(reset) begin cnt <= 0; ones_place <= 0; tens_place <= 0; end
        else if(cnt == 3) begin
            cnt <= 0;
            if(ones_place == 9) begin
                ones_place <= 0;
                if (tens_place == 5) tens_place <= 0;
                else tens_place <= tens_place + 1;
            end else begin
                ones_place <= ones_place + 1;
            end
        end else begin
            cnt <= cnt + 1;
        end
    end
	
endmodule

52移位寄存器

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
  
    always @(posedge clk or posedge areset) begin
        if(areset) q <= 0;
        else if(load) q <= data;
        else if(ena) q <= q >> 1;
        else q <= q;            
    end
endmodule

53查找表

module top_module(
  input clk,
  input enable,
  input S,
  input A, B, C,
  output reg Z 
);
  // Write your code here
    reg [7:0]q;
    //initial begin q <= 0; end
    always @(posedge clk) begin
        if(enable) begin q <= {q[6:0], S}; end
        else begin q <= q; end     
    end
    
    always @(*) begin
               	Z = q[{A, B, C}];
    end
endmodule

54ROM

module top_module(
	input	[2:0] addr,
	output	[3:0]	q
);
    reg [3:0]mem[7:0];
    integer i = 0;
    initial begin
        for (i = 0; i < 8; i = i + 1) begin
            mem[i] = i;
        end
    end
    
    assign q = mem[addr];

endmodule

55RAM

module ram_one_port(
input 		  clk,
input		  wr_en,
input 	[2:0]  wr_addr,
input	[15:0] wr_data,
input	[2:0]  rd_addr,
output	[15:0] rd_data);
    
    reg [15:0]mem[7:0];
    initial begin $readmemh("memfile.dat", mem); end
    
    assign rd_data = mem[rd_addr];
    
    always @(posedge clk) begin
        if(wr_en) mem[wr_addr] <= wr_data;
    end

endmodule

56有限状态机

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output reg out);//  

    always @(posedge clk or posedge areset) begin
        if(areset) out <= 1;
        else if(in == 0) out <= ~out;
        else out <= out; 
    end
  
endmodule

57读代码找错误

module top_module (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output [7:0]out  );

    assign out = ({8{~sel}} & a) | ({8{sel}} & b);

endmodule

58编写仿真文件

//`timescale 1ns/1ns

module tb();
reg a,b;

initial begin
    a = 1'b1;
    b = 1'b0;
    #10

    a = 1'b1;
    b = 1'b1;
    #10

    a = 1'b0;
    b = 1'b1;
    #10

    a = 1'b0;
    b = 1'b0;
    #10

    a = 1'b1;
    b = 1'b0;
    #10
    $finish;
end
    
endmodule

59组合逻辑模块仿真

module tb();
reg a,b;
wire q;
  
//对ab信号进行初始化
initial begin
    a = 0; b = 0;
    #3
    b = 1;
    #2
    a = 1; b = 0;
    #2
    b = 1;
    #2
    a = 0; b = 0;
    #2
    a = 0; b = 1;
    #2
    a = 1; b = 0;
    #2
    b = 1;
    #2
    a = 0; b = 0;
    //$finish;
end
  
//例化mymodule模块
mymodule imymodule_1(.a(a), .b(b), .q(q));
  
endmodule


module mymodule(
input a,b,
output q
);
  
assign q = a & b;
  
endmodule

60生成时钟信号

module tb();
wire [2:0]out;//必要输出信号 	
	//信号定义
    reg clk;
    initial clk = 0;
	//信号生成
    always #5 clk = ~clk;
	//模块例化
        dut idut_1(.clk(clk), .out(out));
endmodule

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

61单端口 RAM 仿真

module ram_one_port(
    input   clk,
    input   [1:0] addr,
    input   wr_en,
    input   [7:0] wr_data,
    output  [7:0] rd_data
);
    reg     [7:0] mem[3:0];
    initial
    begin
      mem[0] = 8'b0;
      mem[1] = 8'b0;
      mem[2] = 8'b0;
      mem[3] = 8'b0;
    end
    assign rd_data = mem[addr];
    always@(posedge clk)
    begin
        if(wr_en)
            mem[addr] <= wr_data;
    end
endmodule

module tb(
);
    //信号定义
    reg             clk,wr_en;
    reg     [1:0]   addr;
    reg     [7:0]   wr_data;
    wire    [7:0]   rd_data;
    //信号生成
    initial begin
        clk = 0;
        forever #5 clk = ~clk; //生成周期为10的一个时钟信号
    end
    
    
    initial begin
        addr = 2'b0;
        @(posedge clk);
        repeat(4) begin         //repeat为verilog关键字,表示重复操作
            @(posedge clk);     //等待clk信号的上升沿到来
                #1 addr = addr + 1; //clk上升沿1个时间单位后,addr加一
        end
    end
    
    
    initial begin
        wr_en = 0;
        #16;            //延时一段时间,
        @(posedge clk);
        #1 wr_en = 1;
        @(posedge clk);
        @(posedge clk);
        #1 wr_en = 0;
    end
    
    
    initial begin
        wr_data = 8'h0;
        repeat(4) begin
            wait(wr_en==1'b1);
            #1 wr_data = $random%256;
            @(posedge clk);
        end
    end
    
    //例化被测模块
    
    ram_one_port ram_inst(
        .clk(clk),
        .wr_en(wr_en),
        .addr(addr),
        .wr_data(wr_data),
        .rd_data(rd_data)
    );
    
endmodule

100寄存器堆模块

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) begin
        if(A3 != 0) reg_file[A3] <= WD;
    end
	/*待填*/
end

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

endmodule

101程序计数器模块

module top_module(
input              clk,
input              rst,
input              JUMP,
input       [31:0] JUMP_PC,
output reg  [31:0] pc);
    
wire [31:0] pc_plus4;
assign pc_plus4 = pc + 32'h4;
//计算PC
always@(posedge clk or posedge rst)
begin
	/*待填*/
    if(rst == 1) pc <= 32'b0;
    else if(JUMP) pc <= JUMP_PC;
    else pc <= pc_plus4;
end
endmodule

102立即数扩展模块

module top_module(
input 	    [31:0] inst,
output reg	[31:0] out
);
wire	[6:0] opcode;
assign	opcode= inst[6:0];
//立即数扩展
    initial out = 32'b0;
always@(*)
begin
	case(opcode)
        7'b0010111: begin out[31:12] = inst[31:12]; end	//auipc
        7'b0110111: begin out[31:12] = inst[31:12]; end	//lui
        7'b1100011: begin 	//B type
        	out[12] = inst[31];
            out[11] = inst[7];
            out[10:5] = inst[30:25];
            out[4:1] = inst[11:8];
            out[31:13] = {19{out[12]}};
        end
        7'b1101111: begin	//jal
            out[20] = inst[31];
            out[19:12] = inst[19:12];
            out[11] = inst[20];
            out[10:1] = inst[30:21];
            out[31:21] = {10{out[20]}};
        end
        7'b1100111: begin	//jalr->I type
            out[11:0] = inst[31:20];
            out[31:12] = {20{out[11]}};
        end
        7'b0000011: begin	//I type
            out[11:0] = inst[31:20];
            out[31:12] = {20{out[11]}};
        end
        7'b0100011: begin	//S type
            out[11:5] = inst[31:25];
            out[4:0] = inst[11:7];
        end
        7'b0010011: begin	//I type
             out[11:0] = inst[31:20];
            out[31:12] = {20{out[11]}};
        end
        default: out = 32'b0;        
                                     
	endcase
end 
endmodule

103分支判断模块

module top_module(         
input [31:0]	REG1,
input [31:0] 	REG2,
input [2:0]		Type,
output     reg     BrE
);
    
wire signed 	[31:0] signed_REG1;
wire signed 	[31:0] signed_REG2;
//wire unsigned 	[31:0] unsigned_REG1;
//wire unsigned 	[31:0] unsigned_REG2;

assign signed_REG1 = REG1;
assign signed_REG2 = REG2; 
//assign unsigned_REG1 = REG1;
//assign unsigned_REG2 = REG2; 
    
always@(*)
begin
	case(Type)
      	3'b010: BrE = signed_REG1 == signed_REG2 ? 1 : 0;	//beq
        3'b011: BrE = signed_REG1 != signed_REG2 ? 1 : 0;	//bne
        3'b100: BrE = signed_REG1 < signed_REG2 ? 1 : 0;	//blt
        3'b101: BrE = signed_REG1 >= signed_REG2 ? 1 : 0;	//bge
        
        3'b110: begin	//bltu
            case({signed_REG1[31], signed_REG2[31]})
                2'b00: BrE = signed_REG1 < signed_REG2;
                2'b01: BrE = 1;
                2'b10: BrE = 0;
                2'b11: BrE = signed_REG1 < signed_REG2;
            endcase
        end
        3'b111: begin	//bgeu
            case({signed_REG1[31], signed_REG2[31]})
                2'b00: BrE = signed_REG1 >= signed_REG2;
                2'b01: BrE = 0;
                2'b10: BrE = 1;
                2'b11: BrE = signed_REG1 >= signed_REG2;
            endcase
        end
        default: BrE = 0;
    	/*待填*/  
	endcase
end
endmodule

104ALU模块

module top_module(
input [31:0] SrcA,SrcB,
input [3:0]  func,
output reg [31:0] ALUout
);

wire signed [31:0] signed_a;
wire signed [31:0] signed_b;

assign signed_a = SrcA;
assign signed_b = SrcB;

always@(*)
begin
  case(func)
      4'b0000: ALUout = signed_a + signed_b;    //add
      4'b1000: ALUout = signed_a - signed_b;    //sub
      4'b0001: ALUout = signed_a << signed_b[4:0];  //sll
      4'b0010: ALUout = signed_a < signed_b ? 1 : 0;    //lt
      4'b0011: begin    //ltu
        case({signed_a[31], signed_b[31]})
            2'b00: ALUout = signed_a < signed_b;
            2'b01: ALUout = 1;
            2'b10: ALUout = 0;
            2'b11: ALUout = signed_a < signed_b;
      endcase
      end
      4'b0100: ALUout = signed_a ^ signed_b;    //xor
      4'b0101: ALUout = signed_a >> signed_b[4:0];  //srl
      4'b1101: ALUout = signed_a >>> signed_b[4:0]; //sra
      4'b0110: ALUout = signed_a | signed_b;    //or
      4'b0111: ALUout = signed_a & signed_b;    //and
      4'b1110: ALUout = signed_b;       //
      default: ALUout = 0;
		/*待填*/
	endcase
end 

endmodule

105存储器

module top_module(
input           clk,
input   [31:0]  im_addr,
output  [31:0]  im_dout,

input   [2:0]   dm_rd_ctrl,
input   [1:0]   dm_wr_ctrl,
input   [31:0]  dm_addr,
input   [31:0]  dm_din,
output reg  [31:0]  dm_dout
);

reg     [3:0]   byte_en;
reg     [31:0]  mem[0:4095];    //4K*32 = 16KB
reg     [31:0]  mem_out;

integer i;
initial
begin
    for(i=0;i<4095;i=i+1) mem[i] = 0;
end

initial
begin
  $readmemh("./problem/inst.dat",mem);
end

assign im_dout = {im_addr[31:14], im_addr[1:0]} == 0 ? mem[im_addr] : 0;

//由于不能跨单位读取数据,地址最低两位的数值决定了当前单位能读取到的数据,即mem_out
always@(*)
begin
    case(dm_addr[1:0])
    2'b00:  mem_out = mem[dm_addr[13:2]][31:0];
    2'b01:  mem_out = {8'h0,mem[dm_addr[13:2]][31:8]};
    2'b10:  mem_out = {16'h0,mem[dm_addr[13:2]][31:16]};
    2'b11:  mem_out = {24'h0,mem[dm_addr[13:2]][31:24]};
    endcase
end

always@(*)
begin
    case(dm_rd_ctrl)
        3'b001: begin   //lb
            case(dm_addr[1:0])
                2'b00: dm_dout = {{24{mem[{dm_addr[13:2], 2'b00}][7]}}, mem[{dm_addr[13:2], 2'b00}][7:0]};
                2'b01: dm_dout = {{24{mem[{dm_addr[13:2], 2'b00}][15]}}, mem[{dm_addr[13:2], 2'b00}][15:7]};
                2'b10: dm_dout = {{24{mem[{dm_addr[13:2], 2'b00}][23]}}, mem[{dm_addr[13:2], 2'b00}][23:16]};
                2'b11: dm_dout = {{24{mem[{dm_addr[13:2], 2'b00}][31]}}, mem[{dm_addr[13:2], 2'b00}][31:24]};
        endcase
        end
        3'b010: begin   //lbu
            case(dm_addr[1:0])
                2'b00: dm_dout = {24'b0, mem[{dm_addr[13:2], 2'b00}][7:0]};
                2'b01: dm_dout = {24'b0, mem[{dm_addr[13:2], 2'b00}][15:7]};
                2'b10: dm_dout = {24'b0, mem[{dm_addr[13:2], 2'b00}][23:16]};
                2'b11: dm_dout = {24'b0, mem[{dm_addr[13:2], 2'b00}][31:24]};
        endcase
        end
        3'b011: begin   //lh
            case(dm_addr[1:0])
                2'b00: dm_dout = {{16{mem[{dm_addr[13:2], 2'b00}][15]}}, mem[{dm_addr[13:2], 2'b00}][15:0]};
                2'b10: dm_dout = {{16{mem[{dm_addr[13:2], 2'b00}][31]}}, mem[{dm_addr[13:2], 2'b00}][31:16]};
                default: dm_dout = 0;
            endcase
        end
        3'b100: begin   //lhu
            case(dm_addr[1:0])
                2'b00: dm_dout = {16'b0, mem[{dm_addr[13:2], 2'b00}][15:0]};
                2'b10: dm_dout = {16'b0, mem[{dm_addr[13:2], 2'b00}][31:16]};
                default: dm_dout = 0;
            endcase
        end 
        3'b101: dm_dout = mem_out;      //lw
        default: dm_dout = 0;
    endcase
end

always@(*)
begin
    if(dm_wr_ctrl == 2'b11)
        byte_en = 4'b1111;
    else if(dm_wr_ctrl == 2'b10)
    begin
        if(dm_addr[1] == 1'b1) 
            byte_en = 4'b1100;
        else
            byte_en = 4'b0011;
    end
    else if(dm_wr_ctrl == 2'b01)
    begin
        case(dm_addr[1:0])
        2'b00:  byte_en = 4'b0001;
        2'b01:  byte_en = 4'b0010;
        2'b10:  byte_en = 4'b0100;
        2'b11:  byte_en = 4'b1000;
        endcase
    end
    else
        byte_en = 4'b0000;
end

always@(posedge clk)
begin
    if((byte_en != 1'b0)&&(dm_addr[30:12]==19'b0))
    begin
        case(byte_en)
        	4'b0001: mem[{dm_addr[11:2], 2'b00}][7:0] <= dm_din[7:0];
            4'b0010: mem[{dm_addr[11:2], 2'b00}][15:8] <= dm_din[7:0];
            4'b0100: mem[{dm_addr[11:2], 2'b00}][23:16] <= dm_din[7:0];
            4'b1000: mem[{dm_addr[11:2], 2'b00}][31:24] <= dm_din[7:0];
            4'b0011: mem[{dm_addr[11:2], 2'b00}][15:0] <= dm_din[15:0];
            4'b1100:mem[{dm_addr[11:2], 2'b00}][31:16] <= dm_din[15:0];
            4'b1111:mem[{dm_addr[11:2], 2'b00}] <= dm_din;
        endcase
    end
end
endmodule

106控制器

//module controler(
module top_module(
input     [31:0]  inst,
output            rf_wr_en,
output reg    [1:0]   rf_wr_sel,
output            do_jump,
output reg    [2:0]   BrType,
output            alu_a_sel,
output            alu_b_sel,
output reg    [3:0]   alu_ctrl,
output reg    [2:0]   dm_rd_ctrl,
output reg    [1:0]   dm_wr_ctrl
);

wire    [6:0]   opcode;
wire    [2:0]   funct3;
wire    [6:0]   funct7;

wire    is_lui;
wire    is_auipc;
wire    is_jal;
wire    is_jalr;
wire    is_beq;
wire    is_bne;
wire    is_blt;
wire    is_bge;
wire    is_bltu;
wire    is_bgeu;
wire    is_lb;
wire    is_lh;
wire    is_lw;
wire    is_lbu;
wire    is_lhu;
wire    is_sb;
wire    is_sh;
wire    is_sw;
wire    is_addi;
wire    is_slti;
wire    is_sltiu;
wire    is_xori;
wire    is_ori;
wire    is_andi;
wire    is_slli;
wire    is_srli;
wire    is_srai;
wire    is_add;
wire    is_sub;
wire    is_sll;
wire    is_slt;
wire    is_sltu;
wire    is_xor;
wire    is_srl;
wire    is_sra;
wire    is_or;
wire    is_and;

wire    is_add_type;
wire    is_u_type;
wire    is_jump_type;
wire    is_b_type;
wire    is_r_type;
wire    is_i_type;
wire    is_s_type;

assign  opcode  = inst[6:0];
assign  funct7  = inst[31:25];
assign  funct3  = inst[14:12];

assign  is_lui  = (opcode == 7'h37) ;
assign  is_auipc= (opcode == 7'h17) ;
assign  is_jal  = (opcode == 7'h6F) ;
assign  is_jalr = (opcode == 7'h67) && (funct3 ==3'h0) ;
assign  is_beq  = (opcode == 7'h63) && (funct3 ==3'h0) ;
assign  is_bne  = (opcode == 7'h63) && (funct3 ==3'h1) ;
assign  is_blt  = (opcode == 7'h63) && (funct3 ==3'h4) ;
assign  is_bge  = (opcode == 7'h63) && (funct3 ==3'h5) ;
assign  is_bltu = (opcode == 7'h63) && (funct3 ==3'h6) ;
assign  is_bgeu = (opcode == 7'h63) && (funct3 ==3'h7) ;
assign  is_lb   = (opcode == 7'h03) && (funct3 ==3'h0) ;
assign  is_lh   = (opcode == 7'h03) && (funct3 ==3'h1) ;
assign  is_lw   = (opcode == 7'h03) && (funct3 ==3'h2) ;
assign  is_lbu  = (opcode == 7'h03) && (funct3 ==3'h4) ;
assign  is_lhu  = (opcode == 7'h03) && (funct3 ==3'h5) ;
assign  is_sb   = (opcode == 7'h23) && (funct3 ==3'h0) ;
assign  is_sh   = (opcode == 7'h23) && (funct3 ==3'h1) ;
assign  is_sw   = (opcode == 7'h23) && (funct3 ==3'h2) ;
assign  is_addi = (opcode == 7'h13) && (funct3 ==3'h0) ;
assign  is_slti = (opcode == 7'h13) && (funct3 ==3'h2) ;
assign  is_sltiu= (opcode == 7'h13) && (funct3 ==3'h3) ;
assign  is_xori = (opcode == 7'h13) && (funct3 ==3'h4) ;
assign  is_ori  = (opcode == 7'h13) && (funct3 ==3'h6) ;
assign  is_andi = (opcode == 7'h13) && (funct3 ==3'h7) ;
assign  is_slli = (opcode == 7'h13) && (funct3 ==3'h1) && (funct7 == 7'h00);
assign  is_srli = (opcode == 7'h13) && (funct3 ==3'h5) && (funct7 == 7'h00);
assign  is_srai = (opcode == 7'h13) && (funct3 ==3'h5) && (funct7 == 7'h20);
assign  is_add  = (opcode == 7'h33) && (funct3 ==3'h0) && (funct7 == 7'h00);
assign  is_sub  = (opcode == 7'h33) && (funct3 ==3'h0) && (funct7 == 7'h20);
assign  is_sll  = (opcode == 7'h33) && (funct3 ==3'h1) && (funct7 == 7'h00);
assign  is_slt  = (opcode == 7'h33) && (funct3 ==3'h2) && (funct7 == 7'h00);
assign  is_sltu = (opcode == 7'h33) && (funct3 ==3'h3) && (funct7 == 7'h00);
assign  is_xor  = (opcode == 7'h33) && (funct3 ==3'h4) && (funct7 == 7'h00);
assign  is_srl  = (opcode == 7'h33) && (funct3 ==3'h5) && (funct7 == 7'h00);
assign  is_sra  = (opcode == 7'h33) && (funct3 ==3'h5) && (funct7 == 7'h20);
assign  is_or   = (opcode == 7'h33) && (funct3 ==3'h6) && (funct7 == 7'h00);
assign  is_and  = (opcode == 7'h33) && (funct3 ==3'h7) && (funct7 == 7'h00);

assign  is_add_type = is_auipc | is_jal | is_jalr | is_b_type | is_s_type 
                    | is_lb | is_lh | is_lw | is_lbu | is_lhu | is_add | is_addi ;
assign  is_u_type   = is_lui | is_auipc ;
assign  is_jump_type= is_jal ;
assign  is_b_type   = is_beq | is_bne | is_blt | is_bge | is_bltu | is_bgeu ;
assign  is_r_type   = is_add | is_sub | is_sll | is_slt | is_sltu | is_xor 
                    | is_srl | is_sra | is_or | is_and ;
assign  is_i_type   = is_jalr | is_lb | is_lh | is_lw | is_lbu | is_lhu 
                    | is_addi | is_slti | is_sltiu | is_xori | is_ori | is_andi
                    | is_slli | is_srli | is_srai ;
assign  is_s_type   = is_sb | is_sh | is_sw ;

//rf_wr_en  
assign rf_wr_en     =  is_u_type | is_jump_type | is_i_type | is_r_type /*待填*/ ;  
  
//[1:0]rf_wr_sel
always@(*)
begin
    if(is_jal|is_jalr) rf_wr_sel = 2'b01;
    else if(is_addi|is_slli|is_xori|is_srli|is_srai|is_ori|is_andi|is_r_type|is_u_type) rf_wr_sel = 2'b10;
    else if(is_lb|is_lbu|is_lh|is_lhu|is_lw) rf_wr_sel = 2'b11;
    else rf_wr_sel = 2'b00;
     /*待填*/
end  
  
//do_jump
assign do_jump      =  is_jal|is_jalr/*待填*/ ;
  
//[2:0]BrType
always@(*)
begin
    if(is_beq) BrType = 3'b010;
    else if(is_bne) BrType = 3'b011;
    else if(is_blt) BrType = 3'b100;
    else if(is_bge) BrType = 3'b101;
    else if(is_bltu) BrType = 3'b110;
    else if(is_bgeu) BrType = 3'b111;
    else BrType = 3'b000;
	 /*待填*/
end
  
//alu_a_sel
assign alu_a_sel    =  is_r_type|is_i_type|is_s_type/*待填*/;

//alu_b_sel  
assign alu_b_sel    =  ~is_r_type/*待填*/ ;
  
//alu_ctrl
always@(*)
begin
    if(is_auipc|is_jal|is_jalr|is_b_type|is_s_type|is_lb|is_lbu|is_lh|is_lhu|is_lw|is_add|is_addi) alu_ctrl = 4'b0000;
    else if(is_sub) alu_ctrl = 4'b1000;
    else if(is_sll|is_slli) alu_ctrl = 4'b0001;
    else if(is_srl|is_srli) alu_ctrl = 4'b0101;
    else if(is_sra|is_srai) alu_ctrl = 4'b1101;
    else if(is_slt|is_slti) alu_ctrl = 4'b0010;
    else if(is_sltu|is_sltiu) alu_ctrl = 4'b0011;
    else if(is_xor|is_xori) alu_ctrl = 4'b0100;
    else if(is_or|is_ori) alu_ctrl = 4'b0110;
    else if(is_and|is_andi) alu_ctrl = 4'b0111;
    else if(is_lui) alu_ctrl = 4'b1110;
    else alu_ctrl = 4'b0000;
     /*待填*/
end
  
//[2:0]dm_rd_ctrl
always@(*)
begin
    if(is_lb) dm_rd_ctrl = 3'b001;
    else if(is_lbu) dm_rd_ctrl = 3'b010;
    else if(is_lh) dm_rd_ctrl = 3'b011;
    else if(is_lhu) dm_rd_ctrl= 3'b100;
    else if(is_lw) dm_rd_ctrl = 3'b101;
    else dm_rd_ctrl = 3'b000;
     /*待填*/
end

//[1:0]dm_wr_ctrl
always@(*)
begin
    if(is_sb) dm_wr_ctrl = 2'b01;
    else if(is_sh) dm_wr_ctrl = 2'b10;
    else if(is_sw) dm_wr_ctrl = 2'b11;
    else dm_wr_ctrl = 2'b00;
    /*待填*/
end  
endmodule

107RISC-V单周期CPU

module top_module(
input clk,
input rst
);
wire        clk;
wire        rst;
wire    [31:0]  inst;

wire    [1:0]   rf_wr_sel;
reg     [31:0]  rf_wd;  
wire            rf_wr_en;
wire    [31:0]  rf_rd1,rf_rd2;
  
wire [31:0] pc;
wire [31:0] pc_plus4;
wire do_jump;
wire JUMP;
  
wire    [31:0]  imm_out;
  
wire    [2:0]   comp_ctrl;
wire		BrE;

wire            alu_a_sel;
wire            alu_b_sel;
wire    [31:0]  alu_a,alu_b,alu_out; 
wire    [3:0]   alu_ctrl;
  
wire    [2:0]   dm_rd_ctrl;
wire    [1:0]   dm_wr_ctrl;
wire    [31:0]  dm_dout;
  
always@(*)
begin
    case(rf_wr_sel)
    2'b00:  rf_wd = 32'h0;
    2'b01:  rf_wd = pc_plus4;
    2'b10:  rf_wd = alu_out;
    2'b11:  rf_wd = dm_dout;
    default:rf_wd = 32'h0;
    endcase
end
assign		pc_plus4 = pc + 32'h4;
assign		JUMP = BrE || do_jump;
assign      alu_a = alu_a_sel ? rf_rd1 : pc ;
assign      alu_b = alu_b_sel ? imm_out : rf_rd2 ;

reg_file reg_file0(
	.clk        (clk),
	.A1         (inst[19:15]),
	.A2         (inst[24:20]),
	.A3         (inst[11:7]),
	.WD         (rf_wd),
	.WE         (rf_wr_en),
	.RD1        (rf_rd1),
	.RD2        (rf_rd2)
);
pc	pc0(
	.clk        (clk),
	.rst		(rst),
    .JUMP		(JUMP),
	.JUMP_PC    (pc+imm_out),	//?
	.pc         (pc)
);
imm	imm0(
	.inst		(inst),
	.out    	(imm_out)
);
branch branch0(
	.REG1		(rf_rd1),
	.REG2		(rf_rd2),
	.Type		(comp_ctrl),
 	.BrE		(BrE)
);
alu alu0(
    .SrcA     	(alu_a),
	.SrcB      	(alu_b),
	.func   	(alu_ctrl),
	.ALUout    	(alu_out)
);
mem mem0(
	.clk        (clk),
	.im_addr    (pc),
	.im_dout    (inst),
	.dm_rd_ctrl (dm_rd_ctrl),
	.dm_wr_ctrl (dm_wr_ctrl),
	.dm_addr    (alu_out),
	.dm_din     (rf_rd2),
	.dm_dout    (dm_dout)
);
ctrl ctrl0(
	.inst       (inst),
	.rf_wr_en   (rf_wr_en),
	.rf_wr_sel  (rf_wr_sel),
	.do_jump    (do_jump),
	.BrType		(comp_ctrl),
	.alu_a_sel  (alu_a_sel),
	.alu_b_sel  (alu_b_sel),
	.alu_ctrl   (alu_ctrl),
	.dm_rd_ctrl (dm_rd_ctrl),
	.dm_wr_ctrl (dm_wr_ctrl)
);

endmodule

你可能感兴趣的:(其他,fpga开发,Verilog,HDL,risc-v)