File: t_order_multidriven.v

package info (click to toggle)
verilator 5.038-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 162,552 kB
  • sloc: cpp: 139,204; python: 20,931; ansic: 10,222; yacc: 6,000; lex: 1,925; makefile: 1,260; sh: 494; perl: 282; fortran: 22
file content (193 lines) | stat: -rw-r--r-- 4,670 bytes parent folder | download | duplicates (3)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2013 by Ted Campbell.
// SPDX-License-Identifier: CC0-1.0

//With MULTI_CLK defined shows bug, without it is hidden
`define MULTI_CLK

//bug634

module t (
    input                   i_clk_wr,
    input                   i_clk_rd
    );

    wire                    wr$wen;
    wire    [7:0]           wr$addr;
    wire    [7:0]           wr$wdata;
    wire    [7:0]           wr$rdata;

    wire                    rd$wen;
    wire    [7:0]           rd$addr;
    wire    [7:0]           rd$wdata;
    wire    [7:0]           rd$rdata;

    wire                    clk_wr;
    wire                    clk_rd;

    `ifdef MULTI_CLK
        assign clk_wr = i_clk_wr;
        assign clk_rd = i_clk_rd;
    `else
        assign clk_wr = i_clk_wr;
        assign clk_rd = i_clk_wr;
    `endif

    FooWr u_wr (
        .i_clk      ( clk_wr   ),

        .o_wen      ( wr$wen   ),
        .o_addr     ( wr$addr  ),
        .o_wdata    ( wr$wdata ),
        .i_rdata    ( wr$rdata )
        );

    FooRd u_rd (
        .i_clk      ( clk_rd   ),

        .o_wen      ( rd$wen   ),
        .o_addr     ( rd$addr  ),
        .o_wdata    ( rd$wdata ),
        .i_rdata    ( rd$rdata )
        );

    FooMem u_mem (
        .iv_clk     ( {clk_wr,  clk_rd  } ),
        .iv_wen     ( {wr$wen,  rd$wen  } ),
        .iv_addr    ( {wr$addr, rd$addr } ),
        .iv_wdata   ( {wr$wdata,rd$wdata} ),
        .ov_rdata   ( {wr$rdata,rd$rdata} )
        );

endmodule


// Memory Writer
module FooWr(
    input                   i_clk,

    output                  o_wen,
    output  [7:0]           o_addr,
    output  [7:0]           o_wdata,
    input   [7:0]           i_rdata
    );

    reg     [7:0]           cnt = 0;

    // Count [0,200]
    always @( posedge i_clk )
        if ( cnt < 8'd50 )
            cnt     <= cnt + 8'd1;

    // Write addr in (10,30) if even
    assign o_wen    = ( cnt > 8'd10 ) && ( cnt < 8'd30 ) && ( cnt[0] == 1'b0 );
    assign o_addr   = cnt;
    assign o_wdata  = cnt;

endmodule


// Memory Reader
module FooRd(
    input                   i_clk,

    output                  o_wen,
    output  [7:0]           o_addr,
    output  [7:0]           o_wdata,
    input   [7:0]           i_rdata
    );

    reg     [7:0]           cnt = 0;
    reg     [7:0]           addr_r;
    reg                     en_r;

    // Count [0,200]
    always @( posedge i_clk )
        if ( cnt < 8'd200 )
            cnt     <= cnt + 8'd1;

    // Read data
    assign o_wen    = 0;
    assign o_addr   = cnt - 8'd100;

    // Track issued read
    always @( posedge i_clk )
    begin
        addr_r <= o_addr;
        en_r   <= ( cnt > 8'd110 ) && ( cnt < 8'd130 ) && ( cnt[0] == 1'b0 );
    end

    // Display to console 100 cycles after writer
    always @( negedge i_clk )
        if ( en_r ) begin
`ifdef TEST_VERBOSE
           $display( "MEM[%x] == %x", addr_r, i_rdata );
`endif
           if (addr_r != i_rdata) $stop;
        end

endmodule


// Multi-port memory abstraction
module FooMem(
    input   [2  -1:0]       iv_clk,
    input   [2  -1:0]       iv_wen,
    input   [2*8-1:0]       iv_addr,
    input   [2*8-1:0]       iv_wdata,
    output  [2*8-1:0]       ov_rdata
    );

    FooMemImpl u_impl (
        .a_clk      ( iv_clk  [0*1+:1] ),
        .a_wen      ( iv_wen  [0*1+:1] ),
        .a_addr     ( iv_addr [0*8+:8] ),
        .a_wdata    ( iv_wdata[0*8+:8] ),
        .a_rdata    ( ov_rdata[0*8+:8] ),

        .b_clk      ( iv_clk  [1*1+:1] ),
        .b_wen      ( iv_wen  [1*1+:1] ),
        .b_addr     ( iv_addr [1*8+:8] ),
        .b_wdata    ( iv_wdata[1*8+:8] ),
        .b_rdata    ( ov_rdata[1*8+:8] )
        );

endmodule


// Dual-Port L1 Memory Implementation
module FooMemImpl(
    input                   a_clk,
    input                   a_wen,
    input   [7:0]           a_addr,
    input   [7:0]           a_wdata,
    output reg [7:0]        a_rdata,

    input                   b_clk,
    input                   b_wen,
    input   [7:0]           b_addr,
    input   [7:0]           b_wdata,
    output reg [7:0]        b_rdata
    );

    /* verilator lint_off MULTIDRIVEN */
    reg     [7:0]           mem[0:255];
    /* verilator lint_on  MULTIDRIVEN */

    always @( posedge a_clk )
        if ( a_wen )
            mem[a_addr] <= a_wdata;

    always @( posedge b_clk )
        if ( b_wen )
            mem[b_addr] <= b_wdata;

    always @( posedge a_clk )
        a_rdata <= mem[a_addr];

    always @( posedge b_clk )
        b_rdata <= mem[b_addr];

endmodule