1 |
2 |
himar |
|
2 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
3 |
|
|
//
|
4 |
|
|
// Copyright (c) 2019 Himar Alonso
|
5 |
|
|
//
|
6 |
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 |
|
|
// of this hardware, software, and associated documentation files
|
8 |
|
|
// (the "Product"), to deal in the Product without restriction, including
|
9 |
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
10 |
|
|
// distribute, sublicense, and/or sell copies of the Product, and to permit
|
11 |
|
|
// persons to whom the Product is furnished to do so, subject to the following
|
12 |
|
|
// conditions:
|
13 |
|
|
//
|
14 |
|
|
// The above copyright notice and this permission notice shall be included in
|
15 |
|
|
// all copies or substantial portions of the Product.
|
16 |
|
|
//
|
17 |
|
|
// THE PRODUCT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
|
|
// OUT OF OR IN CONNECTION WITH THE PRODUCT OR THE USE OR OTHER DEALINGS IN THE
|
23 |
|
|
// PRODUCT.
|
24 |
|
|
//
|
25 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
26 |
|
|
// A429 Transmitting Interface
|
27 |
|
|
//
|
28 |
|
|
// Designed by Himar Alonso (himar@opencores.org)
|
29 |
|
|
// Date: 15/08/2019
|
30 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
31 |
|
|
|
32 |
|
|
module a429_tx_iface
|
33 |
|
|
(
|
34 |
|
|
input clk2M,
|
35 |
|
|
input reset,
|
36 |
|
|
input enable,
|
37 |
|
|
input [1:0] speed,
|
38 |
|
|
input par_gen, // NOT implemented yet (data must include valid parity bit)
|
39 |
|
|
input [6:0] gap_bits, // Values between 4 and 64
|
40 |
|
|
input [32:1] data,
|
41 |
|
|
input tx_req,
|
42 |
|
|
output a429_out_a,
|
43 |
|
|
output a429_out_b,
|
44 |
|
|
output ready
|
45 |
|
|
);
|
46 |
|
|
|
47 |
|
|
//////////////////////////////////////////////////////
|
48 |
|
|
// Generate clk429 according to the 'speed' setting //
|
49 |
|
|
//////////////////////////////////////////////////////
|
50 |
|
|
reg clk429 = 1'b0;
|
51 |
|
|
reg [7:0] clk429_counter = 1'b0;
|
52 |
|
|
wire [7:0] clk429_max_count = (speed[0]) ? 8'd19 : 8'd159;
|
53 |
|
|
wire [7:0] clk429_half_count = (speed[0]) ? 8'd10 : 8'd80;
|
54 |
|
|
|
55 |
|
|
always @(posedge clk2M or posedge reset)
|
56 |
|
|
if (reset)
|
57 |
|
|
clk429 <= 1'b0;
|
58 |
|
|
else
|
59 |
|
|
clk429 <= (clk429_counter < clk429_half_count) ? 1'b1 : 1'b0;
|
60 |
|
|
|
61 |
|
|
always @(posedge clk2M or posedge reset)
|
62 |
|
|
if (reset)
|
63 |
|
|
clk429_counter <= 8'b0;
|
64 |
|
|
else if (clk429_counter >= clk429_max_count)
|
65 |
|
|
clk429_counter <= 8'b0;
|
66 |
|
|
else
|
67 |
|
|
clk429_counter <= clk429_counter + 8'b1;
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
/////////////////////////////////////////////////////////////////////////
|
71 |
|
|
// Format the output word by reversing the bits from the 'label' field //
|
72 |
|
|
/////////////////////////////////////////////////////////////////////////
|
73 |
|
|
wire [32:1] a429_formatted_data = {data[32:9], data[1], data[2], data[3],
|
74 |
|
|
data[4], data[5], data[6], data[7], data[8]};
|
75 |
|
|
|
76 |
|
|
////////////////////////
|
77 |
|
|
// Output assignments //
|
78 |
|
|
////////////////////////
|
79 |
|
|
// Generate a429_out_a and a429_out_b using RZ (return to zero) encoding
|
80 |
|
|
// NOTE: Output is only active when transmitting data
|
81 |
|
|
assign a429_out_a = (clk429 & (state == TRANSMITTING)) ? a429_out_a_bit : 1'b0;
|
82 |
|
|
assign a429_out_b = (clk429 & (state == TRANSMITTING)) ? a429_out_b_bit : 1'b0;
|
83 |
|
|
// Get output serial data from shif_reg's LSB
|
84 |
|
|
wire a429_out_a_bit = shift_reg[1];
|
85 |
|
|
wire a429_out_b_bit = ~shift_reg[1];
|
86 |
|
|
// Ready to receive new data when state == IDLE
|
87 |
|
|
assign ready = (state == IDLE);
|
88 |
|
|
|
89 |
|
|
///////////////////////////////////////////////
|
90 |
|
|
// TX state machine parameters and registers //
|
91 |
|
|
///////////////////////////////////////////////
|
92 |
|
|
localparam IDLE = 2'b00;
|
93 |
|
|
localparam TRANSMITTING = 2'b01;
|
94 |
|
|
localparam WAITING = 2'b10;
|
95 |
|
|
|
96 |
|
|
reg [1:0] state;
|
97 |
|
|
reg [32:1] shift_reg;
|
98 |
|
|
reg [4:0] shift_counter;
|
99 |
|
|
reg [6:0] gap_counter;
|
100 |
|
|
|
101 |
|
|
/////////////////////////////////////
|
102 |
|
|
// TX state machine implementation //
|
103 |
|
|
/////////////////////////////////////
|
104 |
|
|
always @(posedge clk429 or posedge reset)
|
105 |
|
|
if (reset) begin
|
106 |
|
|
state <= IDLE;
|
107 |
|
|
shift_reg <= 32'b0;
|
108 |
|
|
shift_counter <= 5'b0;
|
109 |
|
|
gap_counter <= 6'b0;
|
110 |
|
|
end else if (enable) begin
|
111 |
|
|
case (state)
|
112 |
|
|
IDLE:
|
113 |
|
|
//
|
114 |
|
|
// Wait for transmission request
|
115 |
|
|
//
|
116 |
|
|
if (tx_req == 1'b1) begin
|
117 |
|
|
shift_reg <= a429_formatted_data;
|
118 |
|
|
shift_counter <= 5'b11111;
|
119 |
|
|
state <= TRANSMITTING;
|
120 |
|
|
end
|
121 |
|
|
TRANSMITTING:
|
122 |
|
|
//
|
123 |
|
|
// Logical shift right until shift_counter = 0
|
124 |
|
|
//
|
125 |
|
|
begin
|
126 |
|
|
shift_reg <= {shift_reg[1], shift_reg[32:2]};
|
127 |
|
|
if (~|shift_counter) begin
|
128 |
|
|
// Substract state transition time (2 clock cycles)
|
129 |
|
|
// from total waiting time. The specification sets
|
130 |
|
|
// a minimum gap of 4 clock cycles and a maximum
|
131 |
|
|
// gap of 64 clock cycles between data words
|
132 |
|
|
if (gap_bits < 7'd4) // Minimum: 4
|
133 |
|
|
gap_counter <= 7'd2;
|
134 |
|
|
else if (gap_bits > 7'd64) // Maximum: 64
|
135 |
|
|
gap_counter <= 7'd62;
|
136 |
|
|
else
|
137 |
|
|
gap_counter <= gap_bits - 7'd2;
|
138 |
|
|
state <= WAITING;
|
139 |
|
|
end else begin
|
140 |
|
|
shift_counter <= shift_counter - 5'b1;
|
141 |
|
|
end
|
142 |
|
|
end
|
143 |
|
|
WAITING:
|
144 |
|
|
//
|
145 |
|
|
// Wait specified time before fetching next ARINC 429 data word
|
146 |
|
|
//
|
147 |
|
|
if (~|gap_counter) // gap_counter == 0
|
148 |
|
|
state <= IDLE;
|
149 |
|
|
else
|
150 |
|
|
gap_counter <= gap_counter - 7'b1;
|
151 |
|
|
default: // This should never happen
|
152 |
|
|
state <= IDLE;
|
153 |
|
|
endcase
|
154 |
|
|
end else begin // enable == 0
|
155 |
|
|
state <= IDLE;
|
156 |
|
|
shift_reg <= 32'b0;
|
157 |
|
|
shift_counter <= 5'b0;
|
158 |
|
|
gap_counter <= 6'b0;
|
159 |
|
|
end
|
160 |
|
|
|
161 |
|
|
endmodule
|