Chisel-Verilog查找表优先级问题讨论

Chisel-Verilog查找表优先级问题讨论

Chisel 查找表电路优先级问题

verilog ROM的两种写法及区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
方法1
always @(posedge clk )
begin
case(addr0)
6'd0 : data0 <= 8'd214;
6'd1 : data0 <= 8'd213;
6'd2 : data0 <= 8'd212;
6'd3 : data0 <= 8'd211;
6'd4 : data0 <= 8'd210;
6'd5 : data0 <= 8'd209;
6'd6 : data0 <= 8'd208;
6'd7 : data0 <= 8'd207;
方法2
always @(posedge clk )
begin
if(addr1 == 6'd0 ) data1 <= 8'd150;
else if(addr1 == 6'd1 ) data1 <= 8'd149;
else if(addr1 == 6'd2 ) data1 <= 8'd148;
else if(addr1 == 6'd3 ) data1 <= 8'd147;
else if(addr1 == 6'd4 ) data1 <= 8'd146;
else if(addr1 == 6'd5 ) data1 <= 8'd145;
else if(addr1 == 6'd6 ) data1 <= 8'd144;
else if(addr1 == 6'd7 ) data1 <= 8'd143;

方法2是不是带优先级? 实际上是不带优先级
逻辑上if取的条件都是addr1的值,一定是互斥的,综合工具也能自动识别出这种if else
它有别于以下这种情况,这种情况下是真实带有优先级的电路,其中another_cond_A,another_cond_B
是独立的两个输入条件,和addr1的取值可能同时发生,所以不能被综合器当做查找表来对待。

1
2
3
4
5
6
7
8
9
10
always @(posedge clk )
begin
if(addr1 == 6'd0 ) data1 <= 8'd150;
else if(addr1 == 6'd1 ) data1 <= 8'd149;
else if(another_cond_A ) data1 <= 8'd148;
else if(addr1 == 6'd3 ) data1 <= 8'd147;
else if(addr1 == 6'd4 ) data1 <= 8'd146;
else if(another_cond_B ) data1 <= 8'd145;
else if(addr1 == 6'd6 ) data1 <= 8'd144;
else if(addr1 == 6'd7 ) data1 <= 8'd143;

chisel中查找表的写法以及对应电路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
方法一
switch (addr) {
is( 0.U ) { rdata:= 8'd150 }
is( 1.U ) { rdata:= 8'd149 }
is( 2.U ) { rdata:= 8'd148 }
is( 3.U ) { rdata:= 8'd147 }
is( 4.U ) { rdata:= 8'd146 }
is( 5.U ) { rdata:= 8'd145 }
is( 6.U ) { rdata:= 8'd144 }
is( 7.U ) { rdata:= 8'd143 }
}
方法二
val ROM = Vec(Array(150.U,149.U,148.U, 143.U))
val rdata = ROM(addr)

两种方法都会生成以下类似电路,等效CASE语句写法。所以不用担心优先级的问题。

1
2
3
4
5
6
7
8
9
10
always @(posedge clk )
begin
if(addr1 == 6'd0 ) data1 <= 8'd150;
else if(addr1 == 6'd1 ) data1 <= 8'd149;
else if(addr1 == 6'd2 ) data1 <= 8'd148;
else if(addr1 == 6'd3 ) data1 <= 8'd147;
else if(addr1 == 6'd4 ) data1 <= 8'd146;
else if(addr1 == 6'd5 ) data1 <= 8'd145;
else if(addr1 == 6'd6 ) data1 <= 8'd144;
else if(addr1 == 6'd7 ) data1 <= 8'd143;

综合工具对上面电路的处理也是没有优先级的。

综合对比

Verilog DEMO

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
module  caseifelse_top ( 
clk,
in_en0,in_addr0,out_data0,
in_en1,in_addr1,out_data1
);
input clk ;
input in_en0 ;
input in_en1 ;
input [5:0] in_addr0 ;
input [5:0] in_addr1 ;
output [7:0] out_data0 ;
output [7:0] out_data1 ;
reg [7:0] out_data0 ;
reg [7:0] out_data1 ;
reg [5:0] addr0 ;
reg [5:0] addr1 ;
reg en0 ;
reg en1 ;
wire [7:0] data0 ;
wire [7:0] data1 ;

always @(posedge clk )
begin
en0 <= in_en0 ;
en1 <= in_en1 ;
addr0 <= in_addr0 ;
addr1 <= in_addr1 ;
out_data0 <= data0 ;
out_data1 <= data1 ;
end

rom u_rom_table(
.clk (clk ),
.en0 (en0 ),
.addr0 (addr0 ),
.data0 (data0 )
);

ifelse u_ifelse_table(
.clk (clk ),
.en1 (en1 ),
.addr1 (addr1 ),
.data1 (data1 )
);

endmodule


module rom(clk,
rstn,en0,addr0,data0
);

input clk ;
input rstn ;
input en0 ;
input [5:0] addr0 ;
output [7:0] data0 ;
reg [7:0] data0 ;

always @(posedge clk )
begin
case(addr0)
6'd0 : data0 <= 8'd214;
6'd1 : data0 <= 8'd213;
6'd2 : data0 <= 8'd212;
6'd3 : data0 <= 8'd211;
6'd4 : data0 <= 8'd210;
6'd5 : data0 <= 8'd209;
6'd6 : data0 <= 8'd208;
6'd7 : data0 <= 8'd207;
。。。
6'd63: data0 <= 8'd151;
default : data0 <= 8'd0;
endcase
end

endmodule

module ifelse(clk,
en1,addr1,data1
);

input clk ;
input en1 ;
input [5:0] addr1 ;
output [7:0] data1 ;
reg [7:0] data1 ;

always @(posedge clk )
begin
if(addr1 == 6'd0 ) data1 <= 8'd150;
else if(addr1 == 6'd1 ) data1 <= 8'd149;
else if(addr1 == 6'd2 ) data1 <= 8'd148;
else if(addr1 == 6'd3 ) data1 <= 8'd147;
else if(addr1 == 6'd4 ) data1 <= 8'd146;
else if(addr1 == 6'd5 ) data1 <= 8'd145;
else if(addr1 == 6'd6 ) data1 <= 8'd144;
else if(addr1 == 6'd7 ) data1 <= 8'd143;
。。。
else if(addr1 == 6'd63) data1 <= 8'd87;
else data1 <= 8'd1 ;
end

endmodule

综合后的网表 看到两种方法都是基本相同,没有优先级区别

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

module caseifelse_top_ifelse_1 ( clk, en1, addr1, data1 );
input [5:0] addr1;
output [7:0] data1;
input clk, en1;
wire N67, N69, n8, n9, n10, n17, n18, n19, n1, n2, n3, n4, n5;

SDFKCNQD1BWP7T40P140UHVT data1_reg_7_ ( .D(n8), .CN(n10), .SI(n9), .SE(n9),
.CP(clk), .Q(data1[7]) );
SDFKSNQD1BWP7T40P140UHVT data1_reg_6_ ( .SN(n10), .D(addr1[5]), .SI(n9),
.SE(n9), .CP(clk), .Q(data1[6]) );
MB2SRLSDFQD1BWP7T40P140LVT data1_reg_1_0_ ( .D1(n19), .CP(clk), .SE(n9),
.SI(n9), .Q1(data1[1]), .D2(addr1[0]), .Q2(data1[0]) );
MB2SRLSDFQD1BWP7T40P140UHVT data1_reg_5_4_ ( .D1(N69), .CP(clk), .SE(n9),
.SI(n9), .Q1(data1[5]), .D2(n17), .Q2(data1[4]) );
OA21D1BWP7T35P140UHVT U3 ( .A1(n4), .A2(n2), .B(n1), .Z(N67) );
ND2D1BWP7T30P140UHVT U4 ( .A1(addr1[4]), .A2(n1), .ZN(n10) );
ND2D1BWP7T30P140UHVT U5 ( .A1(n2), .A2(n4), .ZN(n1) );
ND3D1BWP7T30P140UHVT U6 ( .A1(addr1[0]), .A2(addr1[1]), .A3(addr1[2]), .ZN(
n4) );
ND2D1BWP7T35P140UHVT U7 ( .A1(addr1[0]), .A2(addr1[1]), .ZN(n3) );
INVD1BWP7T35P140UHVT U8 ( .I(addr1[3]), .ZN(n2) );
INVD1BWP7T35P140UHVT U9 ( .I(addr1[5]), .ZN(n8) );
OAI21D1BWP7T35P140UHVT U10 ( .A1(addr1[0]), .A2(addr1[1]), .B(n3), .ZN(n19)
);
OAI21D1BWP7T35P140UHVT U11 ( .A1(n5), .A2(addr1[2]), .B(n4), .ZN(n18) );
MAOI22D1BWP7T40P140UHVT U14 ( .A1(n10), .A2(n8), .B1(n8), .B2(n10), .ZN(N69)
);
MB2SRLSDFQD1BWP7T40P140UHVT data1_reg_3_2_ ( .D1(N67), .CP(clk), .SE(n9),
.SI(n9), .Q1(data1[3]), .D2(n18), .Q2(data1[2]) );
TIELBWP7T40P140LVT U12 ( .ZN(n9) );
INVD1BWP7T40P140UHVT U13 ( .I(n3), .ZN(n5) );
OAI21D1BWP7T40P140UHVT U15 ( .A1(addr1[4]), .A2(n1), .B(n10), .ZN(n17) );
endmodule


module caseifelse_top_rom_1 ( clk, rstn, en0, addr0, data0 );
input [5:0] addr0;
output [7:0] data0;
input clk, rstn, en0;
wire N235, N237, N238, n7, n14, n15, n16, n1, n2, n3, n4, n5, n6;

SDFQOPPSAD1BWP7T40P140UHVT data0_reg_0_ ( .D(addr0[0]), .SI(n7), .SE(n7),
.CP(clk), .Q(data0[0]) );
MB2SRLSDFQD1BWP7T40P140LVT data0_reg_2_1_ ( .D1(n15), .CP(clk), .SE(n7),
.SI(n7), .Q1(data0[2]), .D2(n16), .Q2(data0[1]) );
MB2SRLSDFQD1BWP7T40P140LVT data0_reg_4_3_ ( .D1(n14), .CP(clk), .SE(n7),
.SI(n7), .Q1(data0[4]), .D2(N235), .Q2(data0[3]) );
MB2SRLSDFQD1BWP7T40P140LVT data0_reg_6_5_ ( .D1(N238), .CP(clk), .SE(n7),
.SI(n7), .Q1(data0[6]), .D2(N237), .Q2(data0[5]) );
AO21D1BWP7T35P140UHVT U3 ( .A1(n6), .A2(n5), .B(n4), .Z(n14) );
AO21D1BWP7T35P140UHVT U4 ( .A1(n3), .A2(n2), .B(n1), .Z(n15) );
INVD1BWP7T35P140UHVT U5 ( .I(addr0[2]), .ZN(n2) );
ND2D1BWP7T35P140UHVT U6 ( .A1(addr0[0]), .A2(addr0[1]), .ZN(n3) );
NR2D1BWP7T35P140UHVT U7 ( .A1(n2), .A2(n3), .ZN(n1) );
INVD1BWP7T35P140UHVT U8 ( .I(addr0[4]), .ZN(n5) );
NR2D1BWP7T35P140UHVT U9 ( .A1(addr0[3]), .A2(n1), .ZN(n6) );
NR2D1BWP7T35P140UHVT U10 ( .A1(n5), .A2(n6), .ZN(n4) );
OAI21D1BWP7T35P140UHVT U11 ( .A1(addr0[0]), .A2(addr0[1]), .B(n3), .ZN(n16)
);
AOI21D1BWP7T35P140UHVT U12 ( .A1(n1), .A2(addr0[3]), .B(n6), .ZN(N235) );
AOI21D1BWP7T35P140UHVT U13 ( .A1(addr0[5]), .A2(n4), .B(N238), .ZN(N237) );
NR2D1BWP7T35P140UHVT U14 ( .A1(n4), .A2(addr0[5]), .ZN(N238) );
TIELBWP7T40P140LVT U15 ( .ZN(n7) );
endmodule

代码目录:/nutstore/2017pc/lab/turbo/scala/work

结论

chisel 虽然生成的电路没有CASE语句,也完全没有问题,
if else的写法也能满足查找表的实现,并不会有优先级的问题

扩展

同样一下两种chisel和verilog的写法对于综合器来说其实都是没有优先级的,
综合器可以根据时序情况将其打平,并不影响电路的功能(本质上每个条件都不
重叠,所以没有真实的优先级物理意义)
因此可以大胆的采用这种写法而不用考虑优先级进位链太长而产生的时序问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  when      (io.swif.K<40.U  ){tiRomStartAddr :=  baseRAny }
.elsewhen (io.swif.K<159.U ){tiRomStartAddr := baseR5 }
.elsewhen (io.swif.K<200.U ){tiRomStartAddr := baseR10 }
.elsewhen (io.swif.K<481.U ){tiRomStartAddr := baseRAny }
.elsewhen (io.swif.K<530.U ){tiRomStartAddr := baseR10 }
.elsewhen (io.swif.K<2881.U){tiRomStartAddr := baseRAny }
.elsewhen (io.swif.K<2480.U){tiRomStartAddr := baseR20 }
.elsewhen (io.swif.K<3160.U){tiRomStartAddr := baseRAny }
.elsewhen (io.swif.K<3210.U){tiRomStartAddr := baseR20 }
.otherwise {tiRomStartAddr := baseRAny }
```

```verilog
if (K<40 ){addr := 5'd0 }
else if (K<159 ){addr := 5'd1 }
else if (K<200 ){addr := 5'd2 }
else if (K<481 ){addr := 5'd4 }
else if (K<530 ){addr := 5'd6 }
else if (K<2881){addr := 5'd0 }
else if (K<2480){addr := 5'd9 }
else if (K<3160){addr := 5'd0 }
else if (K<3210){addr := 5'd8 }
else {addr := 5'd0 }

评论