输出1

module top_module(
    output out
);

assign out = 1;
endmodule

输出0

module top_module(
  output out
);
  // Write your code here
    
assign out = 0;
endmodule

wire

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

多个端口的模块

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

非门

module top_module( input in, output out );
// 请用户在下方编辑代码
 
 assign out = ~in;
    
    
//用户编辑到此为止
endmodule

与门

module top_module(
  input a, 
  input b,
  output out );
// 请用户在下方编辑代码
assign out = a & b;
//用户编辑到此为止
endmodule

或非门

module top_module( 
    input a, 
    input b, 
    output out );
// 请用户在下方编辑代码

    assign out = ~(a|b);
//用户编辑到此为止
endmodule

同或门

module top_module( 
    input a, 
    input b, 
    output out );
// 请用户在下方编辑代码
assign out = ~(a ^ b);
//用户编辑到此为止
endmodule

线网型中间信号

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out,
    output out_n   
); 
// 请用户在下方编辑代码

wire tmp1 = a & b;
wire tmp2 = c & d;

assign out = tmp1 | tmp2;
assign out_n = ~out;

//用户编辑到此为止
endmodule

向量

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 = vec;
assign o0 = vec[0];
assign o1 = vec[1];
assign o2 = vec[2];
// 用户编辑到此为止
endmodule

向量_续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_lo = in[7:0];
    assign out_hi = in[15:8];
endmodule

向量_续2

module top_module(
  input [31:0] in,
  output [31:0] out
);
  // assign out[31:24] = ...;
    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

位操作

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
);
    assign out_not = ~{b,a};
    assign out_or_logical = a || b;
    assign out_or_bitwise = a | b;
endmodule

位操作

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];

endmodule

向量拼接算子

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

向量翻转

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

复制算子

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

复制算子_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

模块例化

module top_module(
  input 	a,
  input 	b,
  output 	out
);
  
// 请用户在下方编辑代码

    
mod_a mod_a_1 (
    .in1 (a),
    .in2 (b),
    .out (out)
);
    

//用户编辑到此为止
endmodule


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

基于端口位置的实例化

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 mod_a_1(out1,out2,a,b,c,d);
// 用户编辑到此为止
endmodule

基于端口名称的实例化

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
);

mod_a mod_a_1(
    .in1 (a),
    .in2 (b),
    .in3 (c),
    .in4 (d),
    .out1 (out1),
    .out2 (out2)
);
  	
endmodule

多个模块的实例化

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 );
    
wire q1,q2;

my_dff my_dff_1(
    .clk (clk),
    .d (d),
    .q (q1)
);

my_dff my_dff_2(
    .clk (clk),
    .d (q1),
    .q (q2)
);

my_dff my_dff_3(
    .clk (clk),
    .d (q2),
    .q (q)
);

    
   
endmodule

模块与向量信号

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] q1;
    wire [7:0] q2;
    wire [7:0] q3;
    my_dff8 my_dff8_1(
        .clk(clk),
        .d(d),
        .q(q1)
    );
    my_dff8 my_dff8_2(
        .clk(clk),
        .d(q1),
        .q(q2)
    );
    my_dff8 my_dff8_3(
        .clk(clk),
        .d(q2),
        .q(q3)
    );
    always @(*) begin
        case(sel)
            2'b00 : q=d;
            2'b01 : q=q1;
            2'b10 : q=q2;
            2'b11 : q=q3;
            default : q=d;
            
        endcase
    end

endmodule

加法器

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 cout;
    
    add16 add16_low(
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(1'b0),
        .cout(cout),
        .sum(sum[15:0])
	);
    
    add16 add16_high(
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(cout),
        .sum(sum[31:16])
    );
    
    

endmodule

多层次例化加法器

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

module add1 ( input a, input b, input cin,   output sum, output cout );
    assign {cout,sum} = a + b + cin;
endmodule

module add16(
    input [15:0] a,
    input [15:0] b,
    input cin,
    output [15:0] sum,
    output cout
    );
    
    wire c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15;
    add1 inst_0(.a(a[0]),.b(b[0]),.sum(sum[0]),.cout(c1));
    add1 inst_1(.a(a[1]),.b(b[1]),.sum(sum[1]),.cin(c1),.cout(c2));
    add1 inst_2(.a(a[2]),.b(b[2]),.sum(sum[2]),.cin(c2),.cout(c3));
    add1 inst_3(.a(a[3]),.b(b[3]),.sum(sum[3]),.cin(c3),.cout(c4));
    add1 inst_4(.a(a[4]),.b(b[4]),.sum(sum[4]),.cin(c4),.cout(c5));
    add1 inst_5(.a(a[5]),.b(b[5]),.sum(sum[5]),.cin(c5),.cout(c6));
    add1 inst_6(.a(a[6]),.b(b[6]),.sum(sum[6]),.cin(c6),.cout(c7));
    add1 inst_7(.a(a[7]),.b(b[7]),.sum(sum[7]),.cin(c7),.cout(c8));
    add1 inst_8(.a(a[8]),.b(b[8]),.sum(sum[8]),.cin(c8),.cout(c9));
    add1 inst_9(.a(a[9]),.b(b[9]),.sum(sum[9]),.cin(c9),.cout(c10));
    add1 inst_10(.a(a[10]),.b(b[10]),.sum(sum[10]),.cin(c10),.cout(c11));
    add1 inst_11(.a(a[11]),.b(b[11]),.sum(sum[11]),.cin(c11),.cout(c12));
    add1 inst_12(.a(a[12]),.b(b[12]),.sum(sum[12]),.cin(c12),.cout(c13));
    add1 inst_13(.a(a[13]),.b(b[13]),.sum(sum[13]),.cin(c13),.cout(c14));
    add1 inst_14(.a(a[14]),.b(b[14]),.sum(sum[14]),.cin(c14),.cout(c15));
    add1 inst_15(.a(a[15]),.b(b[15]),.sum(sum[15]),.cin(c15),.cout(cout));
    
    
endmodule

进位选择加法器

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 cout;
add16 add16_low_inst0(
    .a(a[15:0]),
    .b(b[15:0]),
    .cin(1'b0),
    .sum(sum[15:0]),
    .cout(cout)
);
   
wire [15:0] r1;
wire [15:0] r2;

add16 add16_high_inst0(
    .a(a[31:16]),
    .b(b[31:16]),
    .cin(1'b0),
    .sum(r1)
);

add16 add16_high_inst1(
    .a(a[31:16]),
    .b(b[31:16]),
    .cin(1'b1),
    .sum(r2)
);


assign sum[31:16] = cout ? r2 : r1;

endmodule

加法减法器

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] b1;
assign b1 = b ^ {32{sub}};
    
wire cout;
    
add16 add16_low_inst0(
    .a(a[15:0]),
    .b(b1[15:0]),
    .cin(sub),
    .sum(sum[15:0]),
    .cout(cout)
);
    
add16 add16_high_inst0(
    .a(a[31:16]),
    .b(b1[31:16]),
    .cin(cout),
    .sum(sum[31:16])
);
    
    
endmodule

always过程块_组合逻辑

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

always过程块_时序逻辑

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;
    
always @(*) begin
	out_always_comb = a ^ b;
end
    
always @(posedge clk) begin
	out_always_ff <= a ^ b;
end
        
        
//用户编辑到此为止
endmodule

if…else…语句

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

if语句与锁存器

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 = gas_tank_empty;
    end
endmodule

case语句

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)
            3'b000: out = data0;
            3'b001: out = data1;
            3'b010: out = data2;
            3'b011: out = data3;
            3'b100: out = data4;
            3'b101: out = data5;
            default: out = 4'b0000;
            
            
        endcase
    end

endmodule

优先编码器

module top_module(
  input [3:0] in,
  output reg [1:0] pos
);
  // Write your code here
    always @(*) begin
        if (in[0] == 1)
            pos = 2'd0;
        else if (in[1] == 1)
            pos = 2'd1;
        else if (in[2] == 1)
            pos = 2'd2;
        else if (in[3] == 1)
            pos = 2'd3;
        else
            pos = 2'd0;
    
    end
endmodule

casez语句

module top_module(
  input [3:0] in,
  output reg [1:0] pos
);
  // Write your code here
    always @(*) begin
        casez(in)
            4'b???1: pos = 2'd0;
            4'b??1?: pos = 2'd1;
            4'b?1??: pos = 2'd2;
            4'b1???: pos = 2'd3;
            default: pos = 2'd0;
            
        endcase
    end
endmodule

避免锁存器

module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
    
    
    always @(*) begin 
    	left = 1'b0; down = 1'b0; right = 1'b0; up = 1'b0;
        case(scancode)
            16'he06b : left = 1'b1;
            16'he072 : down = 1'b1;
            16'he074 : right = 1'b1;
            16'he075 : up = 1'b1;
        endcase
        
    end

endmodule

条件运算符

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

归约运算符

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

assign parity = ^in;

endmodule

D触发器

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

寄存器

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

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


//用户编辑到此为止
endmodule

有复位功能的寄存器

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

下降沿触发的寄存器

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

异步复位的寄存器

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

带使能的寄存器

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

);

    always @(posedge clk) begin
        if (~resetn)
            q <= 16'b0;
      	else
        	if (byteena[0] == 1)
            	q[7:0] <= d[7:0];
        	if (byteena[1] == 1)
            	q[15:8] <= d[15:8];
        
        
    end

endmodule

触发器+逻辑门

module top_module (
    input clk,
    input in, 
    output reg out);

    always @(posedge clk) begin
       out <= out ^ in; 
        
    end
    
    
endmodule

寄存器+逻辑门

module top_module (
    input clk,
    input x,
    output z
);
    
reg reg1;
reg reg2;
reg reg3;

initial begin
reg1 = 1'b0;
reg2 = 1'b0;
reg3 = 1'b0;
end

    always @(posedge clk) begin
        reg1 <= reg1 ^ x;
        reg2 <= ~reg2 & x;
        reg3 <= ~reg3 | x;
    end
    
assign z =~(reg1 | reg2 | reg3);

endmodule

上升沿检测

module top_module (
    input clk,
    input in,
    output reg out
);
reg old_in;

initial begin
    old_in = 1'b0;
    out = 1'b0;
end

always @(posedge clk) begin
	out <= ~old_in & in;
    old_in <= in;
end


endmodule

双边沿检测

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

    end

endmodule

计数器

module top_module (
    input clk,
    input reset,      // 异步复位,高电平有效,复位值为0
    output reg [3:0] q);

    always @(posedge clk or posedge reset) begin
        if (reset)
            q <= 4'b0;
        else 
            q <= q + 1;
    end
endmodule

十进制计数器

module top_module (
    input 				clk		,	//时钟信号
    input 				reset	,   //同步高电平有效复位信号
    output reg 	[3:0] 	q			//计数结果
);
// 请用户在下方编辑代码

    always @(posedge clk) begin
        if(reset)
            q <= 4'b1;
        else 
            if(q == 4'd10)
            	q <= 1;
        	else
                q <= q+1;
    end


//用户编辑到此为止 
endmodule

带使能的计数器

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)
                if(q == 4'd5)
                    q <= 4'd15;
        		else
                    q <= q - 1;
        	else 
                q <= q;
    end

endmodule

秒表

module top_module(
    input 			clk		,  //4Hz
    input 			reset	,
	output	reg [7:0]	ss
); 
	// Write your code here

    reg [1:0] sum;    
    
    always @(posedge clk) begin 
        if (reset) begin
            ss <= 8'd0;
        	sum <= 2'd0;
        end       
        else
            if (sum == 2'd3) begin
                sum <= 2'd0;
            	if(ss[3:0] == 4'd9) begin
                    ss[3:0] <= 4'd0;
                    ss[7:4] <= ss[7:4] +1'd1;
            	end
        		else
                    ss[3:0] <= ss[3:0] + 1'd1;
            end
        	else 
                sum <= sum + 2'd1;
        		
    end
	
endmodule

移位寄存器

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 <= 4'b0;
        else if (load)
            q <= data;
       	else if(ena)
            q <= q >> 1;
       	else
             q <= q;
        
    end
endmodule

查找表

module top_module(
  input clk,
  input enable,
  input S,
  input A, B, C,
  output reg Z 
);
  // Write your code here
    
reg [7:0] q;
    
    always @(posedge clk) begin
        if (enable) begin
            q <= {q[6:0],S};
        end
    end
    
    always @(*) begin
        case({A,B,C})
            3'd0 : Z <= q[0];
            3'd1 : Z <= q[1];
            3'd2 : Z <= q[2];
            3'd3 : Z <= q[3];
            3'd4 : Z <= q[4];
            3'd5 : Z <= q[5];
            3'd6 : Z <= q[6];
            3'd7 : Z <= q[7];
        endcase
    
    end
    
endmodule

ROM

module top_module(
	input	[2:0] addr,
	output	[3:0]	q
);
reg [3:0] ROM [7:0];
initial begin
    ROM[0] = 4'd0;
    ROM[1] = 4'd1;
    ROM[2] = 4'd2;
    ROM[3] = 4'd3;
    ROM[4] = 4'd4;
    ROM[5] = 4'd5;
    ROM[6] = 4'd6;
    ROM[7] = 4'd7;
end

assign q = ROM[addr];
    
endmodule

RAM

同步写 同步写使能 异步读 16位数据宽度 3位地址宽度 ram

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

有限状态机

三段式fsm,第一段考虑如何用组合逻辑电路计算next_state的值,第二段考虑将state更新成next_state的规则,第三段将state和输出关联

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  
  
    parameter A=0, B=1;
	reg state, next_state;
    always @(*) begin    //有限状态机第一段
        // State transition logic
        case(in)
            1'b0 : next_state = ~state;
            1'b1 : next_state = state;
        endcase
	end
	always @(posedge clk, posedge areset) begin    //有限状态机第二段
        // State flip-flops with asynchronous reset
        if(areset)
            state = 1'b1;
        else
            state = next_state;
    end
    //有限状态机第三段,信号输出逻辑
    // assign out = (state == ...);
    assign out = state;
endmodule

读代码找错误

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

);

    //assign out = (~sel & a) | (sel & b);
	assign out = sel ? b : a;
endmodule

编写仿真文件

`timescale 1ns/1ns
module tb(
);
reg a,b;
    
initial begin
   a = 1'b1; b = 1'b0;
   #10 b = 1'b1;
   #10 a = 1'b0;
   #10 b = 1'b0;
   #10 a = 1'b1;
end
    
    
    
endmodule

组合逻辑模块仿真

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 b = 1;
  #2 a = 1; b = 0;
  #2 b = 1;
  #2 a = 0; b = 0;
end
    
//例化mymodule模块
mymodule inst0(
    .a(a),
    .b(b),
    .q(q)
    );
  
endmodule


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

生成时钟信号

module tb();
wire [2:0]out;//必要输出信号 	
	//信号定义
	//信号生成
	//模块例化
    
reg clk;
initial begin
    clk = 1'b0;
end
always #5 clk <= ~clk;

dut inst0(
    .clk(clk),
    .out(out)
);
    
endmodule

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

单端口 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;
    end
    
    initial begin
       addr = 2'b0;
       repeat(4) begin
       		addr = addr + 1'b1;
       end        
    end
    
    initial begin
    	wr_en = 1'b0;
        repeat(5) begin
            @(posedge clk);
        end
        #1 wr_en = 1'b1;
        repeat(4) begin
            @(posedge clk);
        end
        wr_en = 1'b1;
    end
    
    initial begin
    	wr_data = 8'b0;
        repeat(2) begin
            @(posedge clk);
        end
        repeat(3) begin
            @(posedge clk);
            #1 wr_data = $random%256;
        end
        
    end
    
    
    ram_one_port inst0(
        .clk(clk),
        .wr_en(wr_en),
        .addr(addr),
        .wr_data(wr_data),
        .rd_data(rd_data)
    );
endmodule

寄存器堆模块

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'b0)
        reg_file[A3] <= WD;
end

//读取寄存器
assign RD1 = (A1 == 5'b0) ? 32'b0 : reg_file[A1];
assign RD2 = (A2 == 5'b0) ? 32'b0 : reg_file[A2];

endmodule

程序计数器模块

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)
        pc <= 32'b0;
    else if (JUMP)
        pc <= JUMP_PC;
    else
        pc <= pc_plus4;
        
end
endmodule

立即数拓展模块

module top_module(
input 	    [31:0] inst,
output reg	[31:0] out
);
wire	[6:0] opcode;
assign	opcode= inst[6:0];
//立即数扩展
always@(*)
begin
	case(opcode)
        7'b0010111 : out = {inst[31:12],12'b0}; // auipc
        7'b0110111 : out = {inst[31:12],12'b0}; // lui
        7'b1100011 : out = {{19{inst[31]}},inst[31],inst[7],inst[30:25],inst[11:8],1'b0}; // B型
        7'b1101111 : out = {{11{inst[31]}},inst[31],inst[19:12],inst[20],inst[30:21],1'b0}; // jal
        7'b1100111 : out = {{12{inst[31]}},inst[31],inst[19:12],inst[20],inst[30:21]}; // jalr
        7'b0000011 : out = {{20{inst[31]}},inst[31:20]}; // i型访存
        7'b0010011 : out = {{20{inst[31]}},inst[31:20]}; // i型逻辑与移位运算
        7'b0100011 : out = {{20{inst[31]}},inst[31:25],inst[11:7]}; // s型
        default : out = 32'b0;
              
	endcase
end 
endmodule

分支判断模块

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 : BrE = (unsigned_REG1 < unsigned_REG2) ? 1 : 0; // bltu
        3'b111 : BrE = (unsigned_REG1 >= unsigned_REG2) ? 1 : 0; // bgeu
        default : BrE = 1'b0;
	endcase
end
endmodule

ALU模块

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;
      	4'b1000 : ALUout = signed_a - signed_b;
        4'b0001 : ALUout = signed_a << signed_b[4:0];
      	4'b0010 : ALUout = signed_a < signed_b ? 32'b1 : 32'b0;
      	4'b0011 : ALUout = ($unsigned(SrcA) < $unsigned(SrcB)) ? 32'd1 : 32'd0;
      	4'b0100 : ALUout = signed_a ^ signed_b;
      	4'b0101 : ALUout = signed_a >> signed_b[4:0];
        4'b1101 : ALUout = signed_a >>> signed_b[4:0];
      	4'b0110 : ALUout = signed_a | signed_b;
      	4'b0111 : ALUout = signed_a & signed_b;
      	4'b1001 : ALUout = 32'b0;
      	4'b1010 : ALUout = 32'b0;
      	4'b1011 : ALUout = 32'b0;
      	4'b1100 : ALUout = 32'b0;
      	4'b1110 : ALUout = signed_b;
      	4'b1111 : ALUout = 32'b0;
      	
	endcase
end 

endmodule

存储器

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];
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] == 18'b0) && (im_addr[1:0] == 2'b0)) ? mem[im_addr[13:2]] : 32'b0;
    
//由于不能跨单位读取数据,地址最低两位的数值决定了当前单位能读取到的数据,即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 : dm_dout = {{24{mem_out[7]}},mem_out[7:0]};
        3'b010 : dm_dout = {24'b0,mem_out[7:0]};
        3'b011 : dm_dout = {{16{mem_out[15]}},mem_out[15:0]};
        3'b100 : dm_dout = {16'b0,mem_out[15:0]};
        3'b101 : dm_dout = mem_out;
        default : dm_dout = 32'b0;
        
    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[13:2]] <= {mem[dm_addr[13:2]][31:8],dm_din[7:0]};
            4'b0010 : mem[dm_addr[13:2]] <= {mem[dm_addr[13:2]][31:16],dm_din[7:0],mem[dm_addr[13:2]][7:0]};
            4'b0100 : mem[dm_addr[13:2]] <= {mem[dm_addr[13:2]][31:24],dm_din[7:0],mem[dm_addr[13:2]][15:0]};
            4'b1000 : mem[dm_addr[13:2]] <= {dm_din[7:0],mem[dm_addr[13:2]][23:0]};
            4'b0011 : mem[dm_addr[13:2]] <= {mem[dm_addr[13:2]][31:16],dm_din[15:0]};
            4'b1100 : mem[dm_addr[13:2]] <= {dm_din[15:0],mem[dm_addr[13:2]][15:0]};
            4'b1111 : mem[dm_addr[13:2]] <= dm_din[31:0];
            default : ;
        endcase
    end
end
endmodule

控制器

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_jalr || is_jal)
        rf_wr_sel = 2'b01;
    else if(is_addi || is_slti || is_sltiu || is_xori || is_ori || is_andi || is_slli || is_srli || is_srai || is_r_type || is_u_type)
        rf_wr_sel = 2'b10;
    else if(is_lb || is_lh || is_lw || is_lbu || is_lhu)
        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_lh || is_lw || is_lbu || is_lhu)
        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'b1111;
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
⬆︎TOP