voj速通
输出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