1 |
9 |
sinclairrf |
//
|
2 |
|
|
// PERIPHERAL stepper_motor: @NAME@
|
3 |
|
|
// Copyright 2015, Sinclair R.F., Inc.
|
4 |
|
|
//
|
5 |
|
|
// Assemble the byes of the control word from the input bytes.
|
6 |
|
|
@MASTER_BEGIN@
|
7 |
|
|
localparam L__RATEMETHOD_MINUS_1 = @RATEMETHOD@ - 1;
|
8 |
|
|
localparam L__NBITS_RATEMETHOD = clog2(L__RATEMETHOD_MINUS_1);
|
9 |
|
|
@MASTER_END@
|
10 |
|
|
reg [@CONTROL_WIDTH@-1:0] s__input_control_word = {(@CONTROL_WIDTH@){1'b0}};
|
11 |
|
|
always @ (posedge i_clk)
|
12 |
|
|
if (i_rst)
|
13 |
|
|
s__input_control_word <= {(@CONTROL_WIDTH@){1'b0}};
|
14 |
|
|
else if (s_outport && (s_T == 8'd@IX_OUTCONTROL@))
|
15 |
|
|
s__input_control_word <= { s__input_control_word[0+:@CONTROL_WIDTH@-@DW@], s_N };
|
16 |
|
|
else
|
17 |
|
|
s__input_control_word <= s__input_control_word;
|
18 |
|
|
wire [@CONTROL_WIDTH_PACKED@-1:0] s__input_control_word_packed = {
|
19 |
|
|
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+@DW@*((@COUNT_WIDTH@+@DWM1@)/@DW@)+@DW@*((@ACCEL_WIDTH@+@DWM1@)/@DW@)+:@RATECMD_WIDTH@],
|
20 |
|
|
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+@DW@*((@COUNT_WIDTH@+@DWM1@)/@DW@)+:@ACCEL_WIDTH@],
|
21 |
|
|
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+:@COUNT_WIDTH@]
|
22 |
|
|
@OUTMODE_BEGIN@
|
23 |
|
|
, s__input_control_word[0+:@MODE_WIDTH@]
|
24 |
|
|
@OUTMODE_END@
|
25 |
|
|
};
|
26 |
|
|
// Instantiate the control word FIFO and operate its input side.
|
27 |
|
|
reg s__FIFO_wr = 1'b0;
|
28 |
|
|
always @ (posedge i_clk)
|
29 |
|
|
if (i_rst)
|
30 |
|
|
s__FIFO_wr <= 1'b0;
|
31 |
|
|
else
|
32 |
|
|
s__FIFO_wr <= (s_outport && (s_T == 8'd@IX_OUTRECORD@));
|
33 |
|
|
reg [@NBITS_FIFO_DEPTH@:0] s__FIFO_in_addr = {(@NBITS_FIFO_DEPTH@+1){1'b0}};
|
34 |
|
|
always @ (posedge i_clk)
|
35 |
|
|
if (i_rst)
|
36 |
|
|
s__FIFO_in_addr <= {(@NBITS_FIFO_DEPTH@+1){1'b0}};
|
37 |
|
|
else
|
38 |
|
|
s__FIFO_in_addr <= s__FIFO_in_addr + { @NBITS_FIFO_DEPTH@'d0, s__FIFO_wr };
|
39 |
|
|
reg [@CONTROL_WIDTH_PACKED@-1:0] s__FIFO[@FIFO_DEPTH@-1:0];
|
40 |
|
|
always @ (posedge i_clk)
|
41 |
|
|
if (s__FIFO_wr)
|
42 |
|
|
s__FIFO[s__FIFO_in_addr[0+:@NBITS_FIFO_DEPTH@]] <= s__input_control_word_packed;
|
43 |
|
|
// Operate the output side of the FIFO and translate the packed controls into
|
44 |
|
|
// individual signals.
|
45 |
|
|
reg s__FIFO_rd = 1'b0;
|
46 |
|
|
reg [@NBITS_FIFO_DEPTH@:0] s__FIFO_out_addr = {(@NBITS_FIFO_DEPTH@+1){1'b0}};
|
47 |
|
|
always @ (posedge i_clk)
|
48 |
|
|
if (i_rst)
|
49 |
|
|
s__FIFO_out_addr <= {(@NBITS_FIFO_DEPTH@+1){1'b0}};
|
50 |
|
|
else
|
51 |
|
|
s__FIFO_out_addr <= s__FIFO_out_addr + { @NBITS_FIFO_DEPTH@'d0, s__FIFO_rd };
|
52 |
|
|
reg [@CONTROL_WIDTH_PACKED@-1:0] s__output_control_word = @CONTROL_WIDTH_PACKED@'d0;
|
53 |
|
|
always @ (posedge i_clk)
|
54 |
|
|
s__output_control_word <= s__FIFO[s__FIFO_out_addr[0+:@NBITS_FIFO_DEPTH@]];
|
55 |
|
|
wire [@RATECMD_WIDTH@-1:0] s__next_rate = s__output_control_word[@MODE_WIDTH@+@COUNT_WIDTH@+@ACCEL_WIDTH@+:@RATECMD_WIDTH@];
|
56 |
|
|
wire [@ACCEL_WIDTH@-1:0] s__next_accel = s__output_control_word[@MODE_WIDTH@+@COUNT_WIDTH@+:@ACCEL_WIDTH@];
|
57 |
|
|
wire [@COUNT_WIDTH@-1:0] s__next_count = s__output_control_word[@MODE_WIDTH@+:@COUNT_WIDTH@];
|
58 |
|
|
@OUTMODE_BEGIN@
|
59 |
|
|
wire [@MODE_WIDTH@-1:0] s__next_mode = s__output_control_word[0+:@MODE_WIDTH@];
|
60 |
|
|
@OUTMODE_END@
|
61 |
|
|
// Indicate whether or not the FIFO is empty.
|
62 |
|
|
reg s__FIFO_empty = 1'b1;
|
63 |
|
|
always @ (posedge i_clk)
|
64 |
|
|
if (i_rst)
|
65 |
|
|
s__FIFO_empty <=1'b1;
|
66 |
|
|
else
|
67 |
|
|
s__FIFO_empty <= (s__FIFO_out_addr == s__FIFO_in_addr);
|
68 |
|
|
@MASTER_BEGIN@
|
69 |
|
|
// Generate the clock enable for the effective internal clock rate.
|
70 |
|
|
reg s__clk_en = 1'b0;
|
71 |
|
|
reg [L__NBITS_RATEMETHOD-1:0] s__clk_en_count = L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD];
|
72 |
|
|
always @ (posedge i_clk)
|
73 |
|
|
if (i_rst) begin
|
74 |
|
|
s__clk_en <= 1'b0;
|
75 |
|
|
s__clk_en_count <= L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD];
|
76 |
|
|
end else begin
|
77 |
|
|
s__clk_en <= (s__clk_en_count == { {(L__NBITS_RATEMETHOD-1){1'b0}}, 1'b1 });
|
78 |
|
|
if (s__clk_en)
|
79 |
|
|
s__clk_en_count <= L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD];
|
80 |
|
|
else
|
81 |
|
|
s__clk_en_count <= s__clk_en_count - { {(L__NBITS_RATEMETHOD-1){1'b0}}, 1'b1 };
|
82 |
|
|
end
|
83 |
|
|
@MASTER_END@
|
84 |
|
|
// Capture the start strobe from the micro controller.
|
85 |
|
|
reg s__go = 1'b0;
|
86 |
|
|
always @ (posedge i_clk)
|
87 |
|
|
if (i_rst)
|
88 |
|
|
s__go <= 1'b0;
|
89 |
|
|
else if (s_outport && (s_T == 8'd@IX_OUTRUN@))
|
90 |
|
|
s__go <= 1'b1;
|
91 |
|
|
else if (@S__CLK_EN@)
|
92 |
|
|
s__go <= 1'b0;
|
93 |
|
|
else
|
94 |
|
|
s__go <= s__go;
|
95 |
|
|
// Indicate when the controller is running.
|
96 |
|
|
reg s__running = 1'b0;
|
97 |
|
|
wire s__load_next;
|
98 |
|
|
always @ (posedge i_clk)
|
99 |
|
|
if (i_rst)
|
100 |
|
|
s__running <= 1'b0;
|
101 |
|
|
else if (s__go && @S__CLK_EN@)
|
102 |
|
|
s__running <= 1'b1;
|
103 |
|
|
else if (s__load_next && s__FIFO_empty)
|
104 |
|
|
s__running <= 1'b0;
|
105 |
|
|
else
|
106 |
|
|
s__running <= s__running;
|
107 |
|
|
always @ (posedge i_clk)
|
108 |
|
|
if (i_rst)
|
109 |
|
|
s__done <= 1'b1;
|
110 |
|
|
else if (s_outport && (s_T == 8'd@IX_OUTRUN@))
|
111 |
|
|
s__done <= 1'b0;
|
112 |
|
|
else
|
113 |
|
|
s__done <= !s__go && !s__running;
|
114 |
|
|
// Operate the step count
|
115 |
|
|
wire s__step_pre;
|
116 |
|
|
reg [@COUNT_WIDTH@-1:0] s__count = @COUNT_WIDTH@'d0;
|
117 |
|
|
reg s__count_zero = 1'b1;
|
118 |
|
|
always @ (posedge i_clk)
|
119 |
|
|
if (i_rst)
|
120 |
|
|
s__count <= @COUNT_WIDTH@'d0;
|
121 |
|
|
else if (s__load_next && !s__FIFO_empty)
|
122 |
|
|
s__count <= s__next_count;
|
123 |
|
|
else if (@S__CLK_EN@ && s__step_pre)
|
124 |
|
|
s__count <= s__count - { {(@COUNT_WIDTH@-1){1'b0}}, !s__count_zero };
|
125 |
|
|
else
|
126 |
|
|
s__count <= s__count;
|
127 |
|
|
always @ (posedge i_clk)
|
128 |
|
|
if (i_rst)
|
129 |
|
|
s__count_zero <= 1'b1;
|
130 |
|
|
else
|
131 |
|
|
s__count_zero <= (s__count == @COUNT_WIDTH@'d0);
|
132 |
|
|
assign s__load_next = @S__CLK_EN@ && (s__go || s__running && s__step_pre && s__count_zero);
|
133 |
|
|
always @ (posedge i_clk)
|
134 |
|
|
if (i_rst)
|
135 |
|
|
s__FIFO_rd <= 1'b0;
|
136 |
|
|
else
|
137 |
|
|
s__FIFO_rd <= s__load_next && !s__FIFO_empty;
|
138 |
|
|
// Operate the accumulators.
|
139 |
|
|
reg [@ACCUM_WIDTH@-1:0] s__angle = @ACCUM_WIDTH@'d0;
|
140 |
|
|
reg [@RATE_WIDTH@-1:0] s__rate = @RATE_WIDTH@'d0;
|
141 |
|
|
reg [@ACCEL_WIDTH@-1:0] s__accel = @ACCEL_WIDTH@'d0;
|
142 |
|
|
@OUTMODE_BEGIN@
|
143 |
|
|
reg [@MODE_WIDTH@-1:0] s__mode = @MODE_WIDTH@'d0;
|
144 |
|
|
@OUTMODE_END@
|
145 |
|
|
reg [@ACCUM_WIDTH@-1:0] s__angle_presum = @ACCUM_WIDTH@'d0;
|
146 |
|
|
always @ (posedge i_clk)
|
147 |
|
|
if (i_rst)
|
148 |
|
|
s__angle_presum <= @ACCUM_WIDTH@'d0;
|
149 |
|
|
else
|
150 |
|
|
s__angle_presum <= s__angle + { {(@RATE_SCALE@){s__rate[@RATE_WIDTH@-1]}}, s__rate[@RATE_WIDTH@-1:@ACCEL_RES@-@ACCUM_RES@] };
|
151 |
|
|
always @ (posedge i_clk)
|
152 |
|
|
if (i_rst) begin
|
153 |
|
|
s__angle <= @ACCUM_WIDTH@'d0;
|
154 |
|
|
s__rate <= @RATE_WIDTH@'d0;
|
155 |
|
|
s__accel <= @ACCEL_WIDTH@'d0;
|
156 |
|
|
@OUTMODE_BEGIN@
|
157 |
|
|
s__mode <= @MODE_WIDTH@'d0;
|
158 |
|
|
@OUTMODE_END@
|
159 |
|
|
end else if (s__load_next && !s__FIFO_empty) begin
|
160 |
|
|
s__angle <= {(@ACCUM_WIDTH@){s__next_rate[@RATECMD_WIDTH@-1]}};
|
161 |
|
|
s__rate <= { s__next_rate, {(@ACCEL_RES@-@RATE_RES@){1'b0}} };
|
162 |
|
|
s__accel <= s__next_accel;
|
163 |
|
|
@OUTMODE_BEGIN@
|
164 |
|
|
s__mode <= s__next_mode;
|
165 |
|
|
@OUTMODE_END@
|
166 |
|
|
end else if (!s__running || (s__load_next && s__FIFO_empty)) begin
|
167 |
|
|
s__angle <= @ACCUM_WIDTH@'d0;
|
168 |
|
|
s__rate <= @RATE_WIDTH@'d0;
|
169 |
|
|
s__accel <= @ACCEL_WIDTH@'d0;
|
170 |
|
|
@OUTMODE_BEGIN@
|
171 |
|
|
s__mode <= s__mode;
|
172 |
|
|
@OUTMODE_END@
|
173 |
|
|
end else begin
|
174 |
|
|
if (@S__CLK_EN@) begin
|
175 |
|
|
s__angle <= s__angle_presum;
|
176 |
|
|
s__rate <= s__rate + { {(@ACCEL_SCALE@-@RATE_SCALE@){s__accel[@ACCEL_WIDTH@-1]}}, s__accel };
|
177 |
|
|
end else begin
|
178 |
|
|
s__angle <= s__angle;
|
179 |
|
|
s__rate <= s__rate;
|
180 |
|
|
end
|
181 |
|
|
s__accel <= s__accel;
|
182 |
|
|
@OUTMODE_BEGIN@
|
183 |
|
|
s__mode <= s__mode;
|
184 |
|
|
@OUTMODE_END@
|
185 |
|
|
end
|
186 |
|
|
// Generate the direction and step signals.
|
187 |
|
|
assign s__step_pre = (s__angle[@ACCUM_WIDTH@-1] != s__angle_presum[@ACCUM_WIDTH@-1]);
|
188 |
|
|
always @ (posedge i_clk)
|
189 |
|
|
if (i_rst) begin
|
190 |
|
|
o__dir <= 1'b0;
|
191 |
|
|
o__step <= 1'b0;
|
192 |
|
|
end else if (@S__CLK_EN@) begin
|
193 |
|
|
o__dir <= s__rate[@RATE_WIDTH@-1];
|
194 |
|
|
o__step <= s__step_pre;
|
195 |
|
|
end else begin
|
196 |
|
|
o__dir <= o__dir;
|
197 |
|
|
o__step <= o__step;
|
198 |
|
|
end
|
199 |
|
|
@OUTMODE_BEGIN@
|
200 |
|
|
always @ (posedge i_clk)
|
201 |
|
|
if (i_rst)
|
202 |
|
|
o__mode <= @OUTMODEWIDTH@'d0;
|
203 |
|
|
else if (@S__CLK_EN@)
|
204 |
|
|
o__mode <= s__mode;
|
205 |
|
|
else
|
206 |
|
|
o__mode <= o__mode;
|
207 |
|
|
@OUTMODE_END@
|