Lane
数字逻辑设计对Verilog使用的记录

数字逻辑设计对Verilog使用的记录

分享网站

一个非常优质的训练verilog代码能力的网站

introduction

进行大作业手撕verilog时会出现很多奇奇怪怪的报错喵,所以我就在这里简简单单整理一下叭。

记录

  • 在Verilog中,wire数据类型不能在always块中被赋值,wire类型只能通过连续赋值或模块端口赋值来改变。如果你需要在always块中改变变量的值,你应该使用reg类型。但是当你需要在always块中要对变量p0至p8做清零操作,并且你在setqi a1模块端口中也需要进行赋值操作,这导致了命名空间的冲突。
    解决这个问题的一个可行的方案是你可以使用额外的reg类型的变量在always块中操作。这意味着你需要对每个p都定义一个wire和reg配对。在always块中,你可以继续对reg类型的变量进行赋值操作。然后,你可以通过连续赋值语句将wire类型的变量设置为对应的reg类型的变量的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
wire [2:0]w_p0, w_p1, w_p2, w_p3, w_p4, w_p5, w_p6, w_p7, w_p8;
reg [2:0]r_p0 = 0, r_p1 = 0, r_p2 = 0, r_p3 = 0, r_p4 = 0, r_p5 = 0, r_p6 = 0, r_p7 = 0, r_p8 = 0;
reg count = 1;

//连续赋值将wire变量设置为对应的reg变量的值
assign w_p0 = r_p0;
assign w_p1 = r_p1;
assign w_p2 = r_p2;
assign w_p3 = r_p3;
assign w_p4 = r_p4;
assign w_p5 = r_p5;
assign w_p6 = r_p6;
assign w_p7 = r_p7;
assign w_p8 = r_p8;

setqi a1(.count(count), .sw(sw), .p0(w_p0), .p1(w_p1), .p2(w_p2), .p3(w_p3), .p4(w_p4), .p5(w_p5), .p6(w_p6), .p7(w_p7), .p8(w_p8), .stop(stop));

always @(posedge stop)
begin
r_p0 <= 0; r_p1 <= 0; r_p2 <= 0; r_p3 <= 0; r_p4 <= 0; r_p5 <= 0; r_p6 <= 0; r_p7 <= 0; r_p8 <= 0; //进行清零操作
//引入vga图片显示game over
end
  • 仿真中需要改变的变量一定是reg类型

verilog基础知识

矢量操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
取反操作
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
//如果为 assign out[7:0]=in[0:7] 会报错

矢量亦可以复制
{5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f)
{2{a,b,c}} // The same as {a,b,c,a,b,c}
{3'd5, {2{3'd6}}} // 9'b101_110_110. It's a concatenation of 101 with
// the second vector, which is two copies of 3'b110.
module top_module (
input [7:0] in,
output [31:0] out );//

// assign out = { replicate-sign-bit , the-input };
assign out={ {24{in[7]}},in};
endmodule//括号一定不能少打

多个复制问题
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 = ~{ ... } ^ { ... };
assign out=~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}}^{5{a,b,c,d,e}};
endmodule

多模块以及选择器:(模块一定要注意对应位置不要出错,太关键了)
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] q1,q2,q3;
my_dff8 a1(clk,d,q1);
my_dff8 a2(clk,q1,q2);
my_dff8 a3(clk,q2,q3);
always @(*) begin
case(sel)
2'b00:q=d;
2'b01:q=q1;
2'b10:q=q2;
default:q=q3;
endcase
end
endmodule

分线与加法器
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] sum1,sum2;
wire cout1,cout2;
add16 a1(a[15:0],b[15:0],0,sum1,cout1);
add16 a2(a[31:16],b[31:16],cout1,sum2,cout2);
assign sum={sum2,sum1};
endmodule

简单加法器
module add1 ( input a, input b, input cin, output sum, output cout );
assign sum=a^b^cin;
assign cout=(a & b) | (b & cin) | (cin & a);
// Full adder module here

endmodule

加减法 需要注意的是按位与必须两者都要相同位数,则需要进行复制操作
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] b1;
wire [15:0] sum1,sum2;
wire cout1,cout2;
assign b1=b^{32{sub}};
add16 a1(a[15:0],b1[15:0],sub,sum1,cout1);
add16 a2(a[31:16],b1[31:16],cout1,sum2,cout2);
assign sum={sum2,sum1};
endmodule

if语句运用 需要注意的是寄存器必须改变状态
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //

always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer=0;
end

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

endmodule

计组lab记录

lab1

任务一 根据结构图写ALU代码

  • 变量前后不一致很关键,如果发现仿真时有不确定变量一定要注意变量
    (大小写或者0和O很容易混淆)

lab2

  • 进行cpu测试模块的书写
  • 但是最后生成比特流时报了离谱的错误
  • 但是连线后面变量仔细琢磨了没有大的问题

lab3

lab3-1 手搓乘法器

  • 很重要的一点是要弄明白Verilog语言中always语句的并发执行,这和我们以前接触过的高级语言不同,Verilog代码中的语句可以不按顺序执行,这个有点像多线程,也就是说多个任务同时进行。
    上面的代码中共有5个always语句,每个always语句都是时钟信号clk的上跳沿触发,也就是说当clk从0变为1的时候,会触发always语句的执行。
本文作者:Lane
本文链接:https://lakerswillwin.github.io/2024/06/15/computerdesign/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可