summaryrefslogtreecommitdiff
path: root/rtl/wb2axip/axisrandom.v
blob: 43d91f9c242e6af5427a82e035a9bfce3f3a89c7 (plain)
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
////////////////////////////////////////////////////////////////////////////////
//
// Filename: 	axisrandom
// {{{
// Project:	WB2AXIPSP: bus bridges and other odds and ends
//
// Purpose:	An AXI-stream based pseudorandom noise generator
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
// }}}
// Copyright (C) 2020-2024, Gisselquist Technology, LLC
// {{{
//
// This file is part of the WB2AXIP project.
//
// The WB2AXIP project contains free software and gateware, licensed under the
// Apache License, Version 2.0 (the "License").  You may not use this project,
// or this file, except in compliance with the License.  You may obtain a copy
// of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
// License for the specific language governing permissions and limitations
// under the License.
//
////////////////////////////////////////////////////////////////////////////////
// }}}
//
`default_nettype none
//
module	axisrandom #(
		// {{{
		localparam	C_AXIS_DATA_WIDTH = 32
		// }}}
	) (
		// {{{
		input	wire					S_AXI_ACLK,
		input	wire					S_AXI_ARESETN,
		//
		output	reg					M_AXIS_TVALID,
		input	wire					M_AXIS_TREADY,
		output	reg	[C_AXIS_DATA_WIDTH-1:0]		M_AXIS_TDATA
		// }}}
	);

	localparam	INITIAL_FILL = { 1'b1, {(C_AXIS_DATA_WIDTH-1){1'b0}} };
	localparam	LGPOLY = 31;
	localparam [LGPOLY-1:0]			CORE_POLY = { 31'h00_00_20_01 };
	localparam [C_AXIS_DATA_WIDTH-1:0]	POLY
				= { CORE_POLY, {(C_AXIS_DATA_WIDTH-31){1'b0}} };

	// M_AXIS_TVALID
	// {{{
	initial	M_AXIS_TVALID = 1'b0;
	always @(posedge S_AXI_ACLK)
	if (!S_AXI_ARESETN)
		M_AXIS_TVALID <= 1'b0;
	else
		M_AXIS_TVALID <= 1'b1;
	// }}}

	// M_AXIS_TDATA
	// {{{
	//
	// Note--this setup is *FAR* from cryptographically random.
	//
	initial	M_AXIS_TDATA = INITIAL_FILL;
	always @(posedge S_AXI_ACLK)
	if (!S_AXI_ARESETN)
		M_AXIS_TDATA <= INITIAL_FILL;
	else if (M_AXIS_TREADY)
	begin
		M_AXIS_TDATA <= M_AXIS_TDATA >> 1;
		M_AXIS_TDATA[C_AXIS_DATA_WIDTH-1] <= ^(M_AXIS_TDATA & POLY);
	end
	// }}}

	// Verilator lint_off UNUSED
	// {{{
	wire	unused;
	assign	unused = &{ 1'b0 };
	// Verilator lint_on  UNUSED
	// }}}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Formal properties used in verfiying this core
// {{{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
`ifdef	FORMAL
	reg	f_past_valid;

	initial	f_past_valid = 1'b0;
	always @(posedge S_AXI_ACLK)
		f_past_valid <= 1'b1;

	always @(*)
	if (!f_past_valid)
		assume(!S_AXI_ARESETN);

	// Make certain this polynomial will never degenerate, and so that
	// this random number stream will go on for ever--eventually repeating
	// after 2^LGPOLY-1 (hopefully) elements.
	always @(*)
		assert(M_AXIS_TDATA[C_AXIS_DATA_WIDTH-1
				:C_AXIS_DATA_WIDTH-LGPOLY] != 0);

	// AXI stream has only one significant property
	// {{{
	// Here we'll modify it slightly for our purposes
	always @(posedge S_AXI_ACLK)
	if (!f_past_valid || $past(!S_AXI_ARESETN))
		assert(!M_AXIS_TVALID);
	else begin
		assert(M_AXIS_TVALID);
		if ($past(M_AXIS_TVALID && !M_AXIS_TREADY))
			// Normally I'd assesrt M_AXIS_TVALID here, not above,
			// but this core *ALWAYS* produces data
			assert($stable(M_AXIS_TDATA));
		else if ($past(M_AXIS_TVALID))
			// Insist that the data always changes otherwise
			assert($changed(M_AXIS_TDATA));
	end
	// }}}
`endif
// }}}
endmodule