Skip to content

Commit d96fb65

Browse files
committed
axi_lite_lfsr: Add an AXI4 and AXI4 Lite LFSR
1 parent 9b1a082 commit d96fb65

File tree

7 files changed

+353
-0
lines changed

7 files changed

+353
-0
lines changed

Bender.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ sources:
4040
- src/axi_join.sv
4141
- src/axi_lite_demux.sv
4242
- src/axi_lite_join.sv
43+
- src/axi_lite_lfsr.sv
4344
- src/axi_lite_mailbox.sv
4445
- src/axi_lite_mux.sv
4546
- src/axi_lite_regs.sv
@@ -55,6 +56,7 @@ sources:
5556
- src/axi_err_slv.sv
5657
- src/axi_dw_converter.sv
5758
- src/axi_id_serialize.sv
59+
- src/axi_lfsr.sv
5860
- src/axi_multicut.sv
5961
- src/axi_to_axi_lite.sv
6062
- src/axi_to_mem_banked.sv

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1111
- Add `axi_dumper` and `axi_dumper_interpret` script to dump log from an AXI bus for debugging purposes.
1212
- Add FuseSoC and Vivado XSIM limited test to CI
1313
- `assign.svh`: Add macros to assign flat buses using the Vivado naming style.
14+
- `axi_lfsr` and `axi_lite_lfsr`: Add AXI4 and AXI4 Lite LFSR Subordinate devices.
1415

1516
### Changed
1617
- Improve compatibility with FuseSoC

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ In addition to the documents linked in the following table, we are setting up [d
3939
| [`axi_isolate`](src/axi_isolate.sv) | A module that can isolate downstream slaves from receiving new AXI4 transactions. | |
4040
| [`axi_iw_converter`](src/axi_iw_converter.sv) | Convert between any two AXI ID widths. | [Doc][doc.axi_iw_converter] |
4141
| [`axi_join`](src/axi_join.sv) | A connector that joins two AXI interfaces. | |
42+
| [`axi_lfsr`](src/axi_lfsr.sv) | AXI4-attached LFSR; read returns pseudo-random data, writes are compressed into a checksum. | |
4243
| [`axi_lite_demux`](src/axi_lite_demux.sv) | Demultiplexes an AXI4-Lite bus from one slave port to multiple master ports. | [Doc](doc/axi_lite_demux.md) |
4344
| [`axi_lite_join`](src/axi_lite_join.sv) | A connector that joins two AXI-Lite interfaces. | |
45+
| [`axi_lite_lfsr`](src/axi_lite_lfsr.sv) | AXI4-Lite-attached LFSR; read returns pseudo-random data, writes are compressed into a checksum. | |
4446
| [`axi_lite_mailbox`](src/axi_lite_mailbox.sv) | A AXI4-Lite Mailbox with two slave ports and usage triggered irq. | [Doc](doc/axi_lite_mailbox.md) |
4547
| [`axi_lite_mux`](src/axi_lite_mux.sv) | Multiplexes AXI4-Lite slave ports down to one master port. | [Doc](doc/axi_lite_mux.md) |
4648
| [`axi_lite_regs`](src/axi_lite_regs.sv) | AXI4-Lite registers with optional read-only and protection features. | [Doc][doc.axi_lite_regs] |

axi.core

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ filesets:
3131
- src/axi_join.sv
3232
- src/axi_lite_demux.sv
3333
- src/axi_lite_join.sv
34+
- src/axi_lite_lfsr.sv
3435
- src/axi_lite_mailbox.sv
3536
- src/axi_lite_mux.sv
3637
- src/axi_lite_regs.sv
@@ -46,6 +47,7 @@ filesets:
4647
- src/axi_err_slv.sv
4748
- src/axi_dw_converter.sv
4849
- src/axi_id_serialize.sv
50+
- src/axi_lfsr.sv
4951
- src/axi_multicut.sv
5052
- src/axi_to_axi_lite.sv
5153
- src/axi_to_mem_banked.sv

src/axi_lfsr.sv

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright 2022 ETH Zurich and University of Bologna.
2+
// Copyright and related rights are licensed under the Solderpad Hardware
3+
// License, Version 0.51 (the "License"); you may not use this file except in
4+
// compliance with the License. You may obtain a copy of the License at
5+
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6+
// or agreed to in writing, software, hardware and materials distributed under
7+
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Authors:
12+
// - Thomas Benz <tbenz@iis.ee.ethz.ch>
13+
14+
`include "axi/typedef.svh"
15+
16+
/// AXI4 LFSR Subordinate device. Responds with a pseudo random answer. Serial interface to
17+
/// set the internal state.
18+
module axi_lfsr #(
19+
/// AXI4 Data Width
20+
parameter int unsigned DataWidth = 32'd0,
21+
/// AXI4 Addr Width
22+
parameter int unsigned AddrWidth = 32'd0,
23+
/// AXI4 Id Width
24+
parameter int unsigned IdWidth = 32'd0,
25+
/// AXI4 User Width
26+
parameter int unsigned UserWidth = 32'd0,
27+
/// AXI4 request struct definition
28+
parameter type axi_req_t = logic,
29+
/// AXI4 response struct definition
30+
parameter type axi_rsp_t = logic
31+
)(
32+
/// Rising-edge clock
33+
input logic clk_i,
34+
/// Active-low reset
35+
input logic rst_ni,
36+
/// Testmode
37+
input logic testmode_i,
38+
/// AXI4 request struct
39+
input axi_req_t req_i,
40+
/// AXI4 response struct
41+
output axi_rsp_t rsp_o,
42+
/// Serial shift data in (write)
43+
input logic w_ser_data_i,
44+
/// Serial shift data out (write)
45+
output logic w_ser_data_o,
46+
/// Serial shift enable (write)
47+
input logic w_ser_en_i,
48+
/// Serial shift data in (read)
49+
input logic r_ser_data_i,
50+
/// Serial shift data out (read)
51+
output logic r_ser_data_o,
52+
/// Serial shift enable (read)
53+
input logic r_ser_en_i
54+
);
55+
56+
/// AXI4 Strobe Width
57+
localparam int unsigned StrbWidth = DataWidth / 8;
58+
59+
/// Address Type
60+
typedef logic [AddrWidth-1:0] addr_t;
61+
/// Data type
62+
typedef logic [DataWidth-1:0] data_t;
63+
/// Strobe Type
64+
typedef logic [StrbWidth-1:0] strb_t;
65+
66+
// AXI Lite typedef
67+
`AXI_LITE_TYPEDEF_AW_CHAN_T(axi_lite_aw_chan_t, addr_t)
68+
`AXI_LITE_TYPEDEF_W_CHAN_T(axi_lite_w_chan_t, data_t, strb_t)
69+
`AXI_LITE_TYPEDEF_B_CHAN_T(axi_lite_b_chan_t)
70+
71+
`AXI_LITE_TYPEDEF_AR_CHAN_T(axi_lite_ar_chan_t, addr_t)
72+
`AXI_LITE_TYPEDEF_R_CHAN_T(axi_lite_r_chan_t, data_t)
73+
74+
`AXI_LITE_TYPEDEF_REQ_T(axi_lite_req_t, axi_lite_aw_chan_t, axi_lite_w_chan_t, axi_lite_ar_chan_t)
75+
`AXI_LITE_TYPEDEF_RESP_T(axi_lite_rsp_t, axi_lite_b_chan_t, axi_lite_r_chan_t)
76+
77+
// AXI Lite buses
78+
axi_lite_req_t axi_lite_req;
79+
axi_lite_rsp_t axi_lite_rsp;
80+
81+
axi_to_axi_lite #(
82+
.AxiAddrWidth ( AddrWidth ),
83+
.AxiDataWidth ( DataWidth ),
84+
.AxiIdWidth ( IdWidth ),
85+
.AxiUserWidth ( UserWidth ),
86+
.AxiMaxWriteTxns ( 'd2 ), // We only have 1 cycle latency; 2 is enough
87+
.AxiMaxReadTxns ( 'd2 ), // We only have 1 cycle latency; 2 is enough
88+
.FallThrough ( 1'b0 ),
89+
.full_req_t ( axi_req_t ),
90+
.full_resp_t ( axi_rsp_t ),
91+
.lite_req_t ( axi_lite_req_t ),
92+
.lite_resp_t ( axi_lite_rsp_t )
93+
) i_axi_to_axi_lite (
94+
.clk_i,
95+
.rst_ni,
96+
.test_i ( testmode_i ),
97+
.slv_req_i ( req_i ),
98+
.slv_resp_o ( rsp_o ),
99+
.mst_req_o ( axi_lite_req ),
100+
.mst_resp_i ( axi_lite_rsp )
101+
);
102+
103+
axi_lite_lfsr #(
104+
.DataWidth ( DataWidth ),
105+
.axi_lite_req_t ( axi_lite_req_t ),
106+
.axi_lite_rsp_t ( axi_lite_rsp_t )
107+
) i_axi_lite_lfsr (
108+
.clk_i,
109+
.rst_ni,
110+
.testmode_i,
111+
.w_ser_data_i,
112+
.w_ser_data_o,
113+
.w_ser_en_i,
114+
.r_ser_data_i,
115+
.r_ser_data_o,
116+
.r_ser_en_i,
117+
.req_i ( axi_lite_req ),
118+
.rsp_o ( axi_lite_rsp )
119+
);
120+
121+
endmodule : axi_lfsr

src/axi_lite_lfsr.sv

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// Copyright 2022 ETH Zurich and University of Bologna.
2+
// Copyright and related rights are licensed under the Solderpad Hardware
3+
// License, Version 0.51 (the "License"); you may not use this file except in
4+
// compliance with the License. You may obtain a copy of the License at
5+
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6+
// or agreed to in writing, software, hardware and materials distributed under
7+
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Authors:
12+
// - Thomas Benz <tbenz@iis.ee.ethz.ch>
13+
14+
`include "common_cells/registers.svh"
15+
16+
/// AXI4 Lite LFSR Subordinate device. Responds with a pseudo random answer. Serial interface to
17+
/// set the internal state.
18+
module axi_lite_lfsr #(
19+
/// AXI4 Lite Data Width
20+
parameter int unsigned DataWidth = 32'd0,
21+
/// AXI4 Lite request struct definition
22+
parameter type axi_lite_req_t = logic,
23+
/// AXI4 Lite response struct definition
24+
parameter type axi_lite_rsp_t = logic
25+
)(
26+
/// Rising-edge clock
27+
input logic clk_i,
28+
/// Active-low reset
29+
input logic rst_ni,
30+
/// Testmode
31+
input logic testmode_i,
32+
/// AXI4 Lite request struct
33+
input axi_lite_req_t req_i,
34+
/// AXI4 Lite response struct
35+
output axi_lite_rsp_t rsp_o,
36+
/// Serial shift data in (write)
37+
input logic w_ser_data_i,
38+
/// Serial shift data out (write)
39+
output logic w_ser_data_o,
40+
/// Serial shift enable (write)
41+
input logic w_ser_en_i,
42+
/// Serial shift data in (read)
43+
input logic r_ser_data_i,
44+
/// Serial shift data out (read)
45+
output logic r_ser_data_o,
46+
/// Serial shift enable (read)
47+
input logic r_ser_en_i
48+
);
49+
50+
/// AXI4 Strobe Width
51+
localparam int unsigned StrbWidth = DataWidth / 8;
52+
53+
logic w_lfsr_en;
54+
logic r_lfsr_en;
55+
56+
logic w_b_fifo_ready;
57+
58+
// LFSR outputs
59+
logic [DataWidth-1:0] w_data_in, w_data_out;
60+
61+
// AW (ignored)
62+
assign rsp_o.aw_ready = !w_ser_en_i;
63+
64+
// W
65+
axi_opt_lfsr #(
66+
.Width ( DataWidth )
67+
) i_axi_opt_lfsr_w (
68+
.clk_i,
69+
.rst_ni,
70+
.en_i ( w_lfsr_en ),
71+
.ser_data_i ( w_ser_data_i ),
72+
.ser_data_o ( w_ser_data_o ),
73+
.ser_en_i ( w_ser_en_i ),
74+
.inp_en_i ( w_lfsr_en ),
75+
.data_i ( w_data_in ),
76+
.data_o ( w_data_out )
77+
);
78+
assign w_lfsr_en = req_i.w_valid & rsp_o.w_ready;
79+
assign rsp_o.w_ready = !w_ser_en_i & w_b_fifo_ready;
80+
81+
// only write bytes with strobe signal enabled
82+
always_comb begin : gen_data_strb_connect
83+
for (int unsigned i = 0; i < StrbWidth; i++) begin : gen_strb_en
84+
if (req_i.w.strb[i] == 1'b0) begin
85+
w_data_in[i*8+:8] = w_data_out[i*8+:8];
86+
end else if (req_i.w.strb[i] == 1'b1) begin
87+
w_data_in[i*8+:8] = req_i.w.data[i*8+:8];
88+
end else begin
89+
w_data_in[i*8+:8] = 'x;
90+
end
91+
end
92+
end
93+
94+
// B
95+
stream_fifo #(
96+
.FALL_THROUGH ( 1'b0 ),
97+
.DATA_WIDTH ( 'd1 ),
98+
.DEPTH ( 'd2 )
99+
) i_stream_fifo_w_b (
100+
.clk_i,
101+
.rst_ni,
102+
.testmode_i,
103+
.flush_i ( 1'b0 ),
104+
.usage_o ( /* NOT CONNECTED */ ),
105+
.data_i ( 1'b0 ),
106+
.valid_i ( req_i.w_valid ),
107+
.ready_o ( w_b_fifo_ready ),
108+
.data_o ( /* NOT CONNECTED */ ),
109+
.valid_o ( w_b_fifo_valid ),
110+
.ready_i ( req_i.b_ready )
111+
);
112+
assign rsp_o.b.resp = axi_pkg::RESP_OKAY;
113+
assign rsp_o.b_valid = w_b_fifo_valid;
114+
115+
// AR (ignored)
116+
assign rsp_o.ar_ready = !w_ser_en_i;
117+
118+
// R
119+
axi_opt_lfsr #(
120+
.Width ( DataWidth )
121+
) i_axi_opt_lfsr_r (
122+
.clk_i,
123+
.rst_ni,
124+
.en_i ( r_lfsr_en ),
125+
.ser_data_i ( r_ser_data_i ),
126+
.ser_data_o ( r_ser_data_o ),
127+
.ser_en_i ( r_ser_en_i ),
128+
.inp_en_i ( 1'b0 ),
129+
.data_i ( /* NOT CONNECTED */ ),
130+
.data_o ( rsp_o.r.data )
131+
);
132+
assign rsp_o.r.resp = axi_pkg::RESP_OKAY;
133+
assign r_lfsr_en = req_i.r_ready & rsp_o.r_valid;
134+
assign rsp_o.r_valid = !r_ser_en_i;
135+
136+
endmodule : axi_lite_lfsr
137+
138+
139+
/// XOR LFSR with tabs based on the [lfsr_table](https://datacipy.cz/lfsr_table.pdf). LFSR has
140+
/// a serial interface to set the initial state
141+
module axi_opt_lfsr #(
142+
parameter int unsigned Width = 32'd0
143+
) (
144+
/// Rising-edge clock
145+
input logic clk_i,
146+
/// Active-low reset
147+
input logic rst_ni,
148+
input logic en_i,
149+
input logic ser_data_i,
150+
output logic ser_data_o,
151+
input logic ser_en_i,
152+
input logic inp_en_i,
153+
input logic [Width-1:0] data_i,
154+
output logic [Width-1:0] data_o
155+
);
156+
157+
/// Number of bits required to hold the LFSR tab configuration
158+
localparam int unsigned LfsrIdxWidth = cf_math_pkg::idx_width(Width);
159+
/// Maximum number of tabs
160+
localparam int unsigned MaxNumTabs = 4;
161+
162+
/// Type specifying the tap positions
163+
typedef logic [LfsrIdxWidth:0] xnor_entry_t [MaxNumTabs-1:0];
164+
xnor_entry_t XnorFeedback;
165+
166+
// the shift register
167+
logic [Width-1:0] reg_d, reg_q;
168+
169+
// the feedback signal
170+
logic xnor_feedback;
171+
172+
always_comb begin : gen_register
173+
174+
// get the parameters
175+
case (Width)
176+
'd8 : XnorFeedback = { 'd8, 'd6, 'd5, 'd4 };
177+
'd16 : XnorFeedback = { 'd16, 'd14, 'd13, 'd11 };
178+
'd32 : XnorFeedback = { 'd32, 'd30, 'd26, 'd25 };
179+
'd64 : XnorFeedback = { 'd64, 'd63, 'd61, 'd60 };
180+
'd128 : XnorFeedback = { 'd128, 'd127, 'd126, 'd119 };
181+
'd256 : XnorFeedback = { 'd256, 'd256, 'd521, 'd246 };
182+
'd512 : XnorFeedback = { 'd512, 'd510, 'd507, 'd504 };
183+
'd1024 : XnorFeedback = { 'd1024, 'd1015, 'd1002, 'd1001 };
184+
default : XnorFeedback = { 'x, 'x, 'x, 'x };
185+
endcase
186+
187+
// shift register functionality
188+
// compression mode
189+
if (inp_en_i) begin
190+
for (int unsigned i = 0; i < Width - 1; i++) begin : gen_comp_conection
191+
reg_d[i] = reg_q[i+1] ^ data_i[i];
192+
end
193+
// generation mode
194+
end else begin
195+
for (int unsigned i = 0; i < Width - 1; i++) begin : gen_gen_conection
196+
reg_d[i] = reg_q[i+1];
197+
end
198+
end
199+
// serial access mode
200+
if (ser_en_i) begin
201+
// new head element
202+
reg_d[Width-1] = ser_data_i;
203+
// LFSR mode
204+
end else begin
205+
xnor_feedback = reg_q[XnorFeedback[MaxNumTabs-1]-1];
206+
for (int unsigned t = 0; t < MaxNumTabs - 1; t++) begin : gen_feedback_path
207+
xnor_feedback = xnor_feedback;
208+
if (XnorFeedback[t] != 0) begin
209+
xnor_feedback = xnor_feedback ^ reg_q[XnorFeedback[t]-1];
210+
end
211+
end
212+
reg_d[Width-1] = inp_en_i ? xnor_feedback ^ data_i[Width-1] : xnor_feedback;
213+
end
214+
end
215+
216+
// connect outputs
217+
assign ser_data_o = reg_q[0];
218+
assign data_o = reg_q;
219+
220+
// state
221+
`FFL(reg_q, reg_d, en_i | ser_en_i, '1, clk_i, rst_ni)
222+
223+
endmodule : axi_opt_lfsr

0 commit comments

Comments
 (0)