1 |
2 |
zpekic |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company: @Home
|
3 |
|
|
-- Engineer: zpekic@hotmail.com
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 02/26/2018 11:13:02 PM
|
6 |
|
|
-- Design Name: Prime number finder
|
7 |
|
|
-- Module Name: sys_prime - Behavioral
|
8 |
|
|
-- Project Name: Wrapper around signed/unsigned multiply/divide
|
9 |
|
|
-- Target Devices: https://www.micro-nova.com/mercury/ + Baseboard
|
10 |
|
|
-- Input devices:
|
11 |
|
|
-- https://store.digilentinc.com/pmod-kypd-16-button-keypad/ (use when SW(0) is off)
|
12 |
|
|
-- https://www.parallax.com/product/28024 (use when SW(0) is on, RX = PMOD(0), TX = PMOD(4), RST = N/C, GND = PMOD_GND)
|
13 |
|
|
-- Tool Versions: ISE 14.7 (nt)
|
14 |
|
|
-- Description:
|
15 |
|
|
--
|
16 |
|
|
-- Dependencies:
|
17 |
|
|
--
|
18 |
|
|
-- Revision:
|
19 |
|
|
-- Revision 0.99 - Kinda works...
|
20 |
|
|
-- Additional Comments:
|
21 |
|
|
----------------------------------------------------------------------------------
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
library IEEE;
|
25 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
26 |
|
|
|
27 |
|
|
-- Uncomment the following library declaration if using
|
28 |
|
|
-- arithmetic functions with Signed or Unsigned values
|
29 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
30 |
|
|
|
31 |
|
|
-- Uncomment the following library declaration if instantiating
|
32 |
|
|
-- any Xilinx leaf cells in this code.
|
33 |
|
|
--library UNISIM;
|
34 |
|
|
--use UNISIM.VComponents.all;
|
35 |
|
|
|
36 |
|
|
use work.sys_primegen_package.all;
|
37 |
|
|
entity sys_primegen is
|
38 |
|
|
Port (
|
39 |
|
|
-- 50MHz on the Mercury board
|
40 |
|
|
CLK: in std_logic;
|
41 |
|
|
-- Master reset button on Mercury board
|
42 |
|
|
USR_BTN: in std_logic;
|
43 |
|
|
-- Switches on baseboard
|
44 |
|
|
-- SW(0) -- 0 enter Arg0 and Arg1 using PMOD keyboard, 1 enter using serial (UART)
|
45 |
|
|
-- SW(1) -- 0 (16/16 or 16*16), 1 (32/16 - divide only)
|
46 |
|
|
-- SW(2) -- 0 (unsigned), 1 (signed)
|
47 |
|
|
-- SW(3) -- 0 (multiply), 1 (divide)
|
48 |
|
|
-- SW(4) -- 0 manual mode (see SW3, 2, 1), 1 find prime numbers using microcoded program
|
49 |
|
|
-- SW(6 downto 5) -- system clock speed
|
50 |
|
|
-- 0 0 1Hz (can be used with SS mode)
|
51 |
|
|
-- 0 1 1024Hz (can be used with SS mode)
|
52 |
|
|
-- 1 0 6.125MHz
|
53 |
|
|
-- 1 1 25MHz
|
54 |
|
|
-- SW(7)
|
55 |
|
|
-- 0 single step mode off (BTN3 should be pressed once to start the system)
|
56 |
|
|
-- 1 single step mode on (use with BTN3)
|
57 |
|
|
SW: in std_logic_vector(7 downto 0);
|
58 |
|
|
-- Push buttons on baseboard
|
59 |
|
|
-- BTN0 - LED display select 0
|
60 |
|
|
-- BTN1 - LED display select 1
|
61 |
|
|
-- BTN2 - start the multiply or divide operation, or find prime algorithm
|
62 |
|
|
-- BTN3 - single step clock cycle forward if in SS mode (NOTE: single press on this button is needed after reset to unlock SS circuit)
|
63 |
|
|
BTN: in std_logic_vector(3 downto 0);
|
64 |
|
|
-- Stereo audio output on baseboard
|
65 |
|
|
--AUDIO_OUT_L, AUDIO_OUT_R: out std_logic;
|
66 |
|
|
-- 7seg LED on baseboard
|
67 |
|
|
A_TO_G: out std_logic_vector(6 downto 0);
|
68 |
|
|
AN: out std_logic_vector(3 downto 0);
|
69 |
|
|
DOT: out std_logic;
|
70 |
|
|
-- 4 LEDs on Mercury board
|
71 |
|
|
LED: out std_logic_vector(3 downto 0);
|
72 |
|
|
-- ADC interface
|
73 |
|
|
-- channel input
|
74 |
|
|
-- 0 Audio Left
|
75 |
|
|
-- 1 Audio Right
|
76 |
|
|
-- 2 Temperature
|
77 |
|
|
-- 3 Light
|
78 |
|
|
-- 4 Pot
|
79 |
|
|
-- 5 Channel 5 (free)
|
80 |
|
|
-- 6 Channel 6 (free)
|
81 |
|
|
-- 7 Channel 7 (free)
|
82 |
|
|
--ADC_MISO: in std_logic;
|
83 |
|
|
--ADC_MOSI: out std_logic;
|
84 |
|
|
--ADC_SCK: out std_logic;
|
85 |
|
|
--ADC_CSN: out std_logic;
|
86 |
|
|
--PMOD interface
|
87 |
|
|
PMOD: inout std_logic_vector(7 downto 0)
|
88 |
|
|
|
89 |
|
|
);
|
90 |
|
|
end sys_primegen;
|
91 |
|
|
|
92 |
|
|
architecture Structural of sys_primegen is
|
93 |
|
|
|
94 |
|
|
component clock_divider is
|
95 |
|
|
Port ( reset : in STD_LOGIC;
|
96 |
|
|
clock : in STD_LOGIC;
|
97 |
|
|
slow : out STD_LOGIC_VECTOR (11 downto 0);
|
98 |
|
|
baud : out STD_LOGIC_VECTOR(7 downto 0);
|
99 |
|
|
fast : out STD_LOGIC_VECTOR (4 downto 0)
|
100 |
|
|
);
|
101 |
|
|
end component;
|
102 |
|
|
|
103 |
|
|
component clocksinglestepper is
|
104 |
|
|
Port ( reset : in STD_LOGIC;
|
105 |
|
|
clock0_in : in STD_LOGIC;
|
106 |
|
|
clock1_in : in STD_LOGIC;
|
107 |
|
|
clock2_in : in STD_LOGIC;
|
108 |
|
|
clock3_in : in STD_LOGIC;
|
109 |
|
|
clocksel : in STD_LOGIC_VECTOR(1 downto 0);
|
110 |
|
|
modesel : in STD_LOGIC;
|
111 |
|
|
singlestep : in STD_LOGIC;
|
112 |
|
|
clock_out : out STD_LOGIC);
|
113 |
|
|
end component;
|
114 |
|
|
|
115 |
|
|
component debouncer8channel is
|
116 |
|
|
Port ( clock : in STD_LOGIC;
|
117 |
|
|
reset : in STD_LOGIC;
|
118 |
|
|
signal_raw : in STD_LOGIC_VECTOR(7 downto 0);
|
119 |
|
|
signal_debounced : out STD_LOGIC_VECTOR(7 downto 0));
|
120 |
|
|
end component;
|
121 |
|
|
|
122 |
|
|
component fourdigitsevensegled is
|
123 |
|
|
Port ( -- inputs
|
124 |
|
|
data : in STD_LOGIC_VECTOR (15 downto 0);
|
125 |
|
|
digsel : in STD_LOGIC_VECTOR (1 downto 0);
|
126 |
|
|
showdigit : in STD_LOGIC_VECTOR (3 downto 0);
|
127 |
|
|
showdot : in STD_LOGIC_VECTOR (3 downto 0);
|
128 |
|
|
showsegments : in STD_LOGIC;
|
129 |
|
|
-- outputs
|
130 |
|
|
anode : out STD_LOGIC_VECTOR (3 downto 0);
|
131 |
|
|
segment : out STD_LOGIC_VECTOR (7 downto 0)
|
132 |
|
|
);
|
133 |
|
|
end component;
|
134 |
|
|
|
135 |
|
|
component signedmultiplier is
|
136 |
|
|
Port ( reset : in STD_LOGIC;
|
137 |
|
|
clk : in STD_LOGIC;
|
138 |
|
|
start : in STD_LOGIC;
|
139 |
|
|
mode: in STD_LOGIC_VECTOR(1 downto 0);
|
140 |
|
|
dividend32: in STD_LOGIC;
|
141 |
|
|
arg0h : in STD_LOGIC_VECTOR (15 downto 0);
|
142 |
|
|
arg0l : in STD_LOGIC_VECTOR (15 downto 0);
|
143 |
|
|
arg1 : in STD_LOGIC_VECTOR (15 downto 0);
|
144 |
|
|
result : out STD_LOGIC_VECTOR (31 downto 0);
|
145 |
|
|
ready : out STD_LOGIC;
|
146 |
|
|
error : out STD_LOGIC;
|
147 |
|
|
zero : out STD_LOGIC;
|
148 |
|
|
sign : out STD_LOGIC;
|
149 |
|
|
debug : out STD_LOGIC_VECTOR(3 downto 0)
|
150 |
|
|
);
|
151 |
|
|
end component;
|
152 |
|
|
|
153 |
|
|
component bin2bcd is
|
154 |
|
|
Port ( reset : in STD_LOGIC;
|
155 |
|
|
clk : in STD_LOGIC;
|
156 |
|
|
start : in STD_LOGIC;
|
157 |
|
|
bin : in STD_LOGIC_VECTOR (15 downto 0);
|
158 |
|
|
ready : out STD_LOGIC;
|
159 |
|
|
bcd : out STD_LOGIC_VECTOR (23 downto 0);
|
160 |
|
|
debug: out STD_LOGIC_VECTOR(3 downto 0));
|
161 |
|
|
end component;
|
162 |
|
|
|
163 |
|
|
component PmodKYPD is
|
164 |
|
|
Port (
|
165 |
|
|
clk : in STD_LOGIC;
|
166 |
|
|
reset: in STD_LOGIC;
|
167 |
|
|
bcdmode: in STD_LOGIC;
|
168 |
|
|
Col : out STD_LOGIC_VECTOR (3 downto 0);
|
169 |
|
|
Row : in STD_LOGIC_VECTOR (3 downto 0);
|
170 |
|
|
key_code: out STD_LOGIC_VECTOR (3 downto 0);
|
171 |
|
|
key_down: out STD_LOGIC
|
172 |
|
|
);
|
173 |
|
|
end component;
|
174 |
|
|
|
175 |
|
|
component UART is
|
176 |
|
|
Generic (
|
177 |
|
|
CLK_FREQ : integer := 50e6; -- system clock frequency in Hz
|
178 |
|
|
BAUD_RATE : integer := 115200; -- baud rate value
|
179 |
|
|
PARITY_BIT : string := "none"; -- type of parity: "none", "even", "odd", "mark", "space"
|
180 |
|
|
USE_DEBOUNCER : boolean := True -- enable/disable debouncer
|
181 |
|
|
);
|
182 |
|
|
Port (
|
183 |
|
|
CLK : in std_logic; -- system clock
|
184 |
|
|
RST : in std_logic; -- high active synchronous reset
|
185 |
|
|
-- UART INTERFACE
|
186 |
|
|
UART_TXD : out std_logic; -- serial transmit data
|
187 |
|
|
UART_RXD : in std_logic; -- serial receive data
|
188 |
|
|
-- USER DATA INPUT INTERFACE
|
189 |
|
|
DATA_IN : in std_logic_vector(7 downto 0); -- input data
|
190 |
|
|
DATA_SEND : in std_logic; -- when DATA_SEND = 1, input data are valid and will be transmit
|
191 |
|
|
BUSY : out std_logic; -- when BUSY = 1, transmitter is busy and you must not set DATA_SEND to 1
|
192 |
|
|
-- USER DATA OUTPUT INTERFACE
|
193 |
|
|
DATA_OUT : out std_logic_vector(7 downto 0); -- output data
|
194 |
|
|
DATA_VLD : out std_logic; -- when DATA_VLD = 1, output data are valid
|
195 |
|
|
FRAME_ERROR : out std_logic -- when FRAME_ERROR = 1, stop bit was invalid
|
196 |
|
|
);
|
197 |
|
|
end component;
|
198 |
|
|
|
199 |
|
|
component rom32x32 is
|
200 |
|
|
Port ( nCS : in STD_LOGIC;
|
201 |
|
|
a : in STD_LOGIC_VECTOR (4 downto 0);
|
202 |
|
|
d : out STD_LOGIC_VECTOR (31 downto 0));
|
203 |
|
|
end component;
|
204 |
|
|
|
205 |
|
|
component sequencer is
|
206 |
|
|
Port ( reset : in STD_LOGIC;
|
207 |
|
|
clk : in STD_LOGIC;
|
208 |
|
|
operation : in STD_LOGIC_VECTOR (2 downto 0);
|
209 |
|
|
condition : in STD_LOGIC;
|
210 |
|
|
directvalue : in STD_LOGIC_VECTOR (7 downto 0);
|
211 |
|
|
uIP : out STD_LOGIC_VECTOR (7 downto 0));
|
212 |
|
|
end component;
|
213 |
|
|
|
214 |
|
|
component alu_with_hex2ascii is
|
215 |
|
|
Port ( a : in STD_LOGIC_VECTOR (15 downto 0);
|
216 |
|
|
b : in STD_LOGIC_VECTOR (15 downto 0);
|
217 |
|
|
bcdmode: in STD_LOGIC;
|
218 |
|
|
operation : in STD_LOGIC_VECTOR (2 downto 0);
|
219 |
|
|
carry_in : in STD_LOGIC;
|
220 |
|
|
carry_out : out STD_LOGIC;
|
221 |
|
|
zero : out STD_LOGIC;
|
222 |
|
|
y : out STD_LOGIC_VECTOR (15 downto 0));
|
223 |
|
|
end component;
|
224 |
|
|
|
225 |
|
|
|
226 |
|
|
signal Reset: std_logic;
|
227 |
|
|
signal clock_main: std_logic;
|
228 |
|
|
signal switch: std_logic_vector(7 downto 0);
|
229 |
|
|
signal button: std_logic_vector(3 downto 0);
|
230 |
|
|
signal led_bus: std_logic_vector(19 downto 0);
|
231 |
|
|
signal display0, display1: std_logic_vector(15 downto 0);
|
232 |
|
|
signal flash: std_logic;
|
233 |
|
|
signal freq2k, freq1k, freq512, freq256, freq128, freq64, freq32, freq16, freq8, freq4, freq2, freq1: std_logic;
|
234 |
|
|
signal freq38400, freq19200, freq9600, freq4800, freq2400, freq1200, freq600, freq300: std_logic;
|
235 |
|
|
signal freq25M, freq12M5, freq6M25, freq3M125, freq1M5625: std_logic;
|
236 |
|
|
|
237 |
|
|
signal arg0, arg1: std_logic_vector(31 downto 0);
|
238 |
|
|
signal key_pulse, rxd_pulse: std_logic;
|
239 |
|
|
signal key_code: std_logic_vector(3 downto 0);
|
240 |
|
|
signal result: std_logic_vector(31 downto 0);
|
241 |
|
|
alias prod_h: std_logic_vector(15 downto 0) is result(31 downto 16);
|
242 |
|
|
alias prod_l: std_logic_vector(15 downto 0) is result(15 downto 0);
|
243 |
|
|
alias quotient: std_logic_vector(15 downto 0) is result(31 downto 16);
|
244 |
|
|
alias remainder: std_logic_vector(15 downto 0) is result(15 downto 0);
|
245 |
|
|
|
246 |
|
|
signal sm_ready, sm_error, sm_zero, sm_sign: std_logic;
|
247 |
|
|
signal sm_control: std_logic_vector(3 downto 0);
|
248 |
|
|
signal sm_input1, sm_input0l, sm_input0h: std_logic_vector(15 downto 0);
|
249 |
|
|
|
250 |
|
|
--signal txd_data: std_logic_vector(7 downto 0);
|
251 |
|
|
signal txd_busy, txd: std_logic;
|
252 |
|
|
signal rxd_data: std_logic_vector(7 downto 0);
|
253 |
|
|
signal rxd_valid, rxd_valid_delayed, rxd_error, uart_send: std_logic;
|
254 |
|
|
signal rxd_pulsecnt: integer range 0 to 15;
|
255 |
|
|
signal kbd_col: std_logic_vector(3 downto 0);
|
256 |
|
|
signal rxd_code: std_logic_vector(4 downto 0);
|
257 |
|
|
signal input_pulse: std_logic;
|
258 |
|
|
signal input_code: std_logic_vector(3 downto 0);
|
259 |
|
|
signal send_previous, send_current: std_logic_vector(7 downto 0);
|
260 |
|
|
|
261 |
|
|
-- specialized "CPU" ---
|
262 |
|
|
signal condition: std_logic;
|
263 |
|
|
signal uIP: std_logic_vector(7 downto 0);
|
264 |
|
|
signal alu_c, alu_z: std_logic;
|
265 |
|
|
signal n, m, i: std_logic_vector(15 downto 0);
|
266 |
|
|
signal alu_y, alu_a, alu_b: std_logic_vector(15 downto 0);
|
267 |
|
|
signal i_bcd, n_bcd: std_logic_vector(23 downto 0);
|
268 |
|
|
signal i_bcdready, n_bcdready: std_logic;
|
269 |
|
|
|
270 |
|
|
signal uInstruction: std_logic_vector(31 downto 0);
|
271 |
|
|
alias u_value: std_logic_vector(7 downto 0) is uInstruction(31 downto 24);
|
272 |
|
|
alias u_muxa: std_logic_vector(2 downto 0) is uInstruction(23 downto 21);
|
273 |
|
|
alias u_muxb: std_logic_vector(2 downto 0) is uInstruction(20 downto 18);
|
274 |
|
|
alias u_alu: std_logic_vector(2 downto 0) is uInstruction(17 downto 15);
|
275 |
|
|
alias u_ci: std_logic is uInstruction(14);
|
276 |
|
|
alias u_i: std_logic is uInstruction(13);
|
277 |
|
|
alias u_m: std_logic is uInstruction(12);
|
278 |
|
|
alias u_n: std_logic is uInstruction(11);
|
279 |
|
|
alias u_mode: std_logic_vector(1 downto 0) is uInstruction(10 downto 9);
|
280 |
|
|
alias u_multdiv: std_logic is uInstruction(8);
|
281 |
|
|
alias u_uart: std_logic is uInstruction(7);
|
282 |
|
|
alias u_opsequence: std_logic_vector(2 downto 0) is uInstruction(6 downto 4);
|
283 |
|
|
alias u_condselect: std_logic_vector(3 downto 0) is uInstruction(3 downto 0);
|
284 |
|
|
-- HACKHACK "faked" ucode control signals
|
285 |
|
|
signal u_i2bcdstart: std_logic;
|
286 |
|
|
signal u_n2bcdstart: std_logic;
|
287 |
|
|
|
288 |
|
|
begin
|
289 |
|
|
|
290 |
|
|
Reset <= USR_BTN;
|
291 |
|
|
|
292 |
|
|
-- DISPLAY
|
293 |
|
|
flash <= (not sm_error) or freq2; -- blink in hold bus mode!
|
294 |
|
|
|
295 |
|
|
display0 <= result(15 downto 0) when switch(4) = '0' else uIP & uInstruction(7 downto 0);
|
296 |
|
|
display1 <= result(31 downto 16) when switch(4) = '0' else alu_y;
|
297 |
|
|
|
298 |
|
|
with button(1 downto 0) select
|
299 |
|
|
led_bus(15 downto 0) <= display0 when "00",
|
300 |
|
|
display1 when "01",
|
301 |
|
|
arg0(15 downto 0) when "10",
|
302 |
|
|
arg1(15 downto 0) when others;
|
303 |
|
|
|
304 |
|
|
LED(3 downto 2) <= sm_sign & sm_zero when switch(4) = '0' else alu_c & condition;
|
305 |
|
|
LED(1) <= sm_ready;
|
306 |
|
|
LED(0) <= clock_main;
|
307 |
|
|
led4x7: fourdigitsevensegled port map (
|
308 |
|
|
-- inputs
|
309 |
|
|
data => led_bus(15 downto 0),
|
310 |
|
|
digsel(1) => freq1k,
|
311 |
|
|
digsel(0) => freq2k,
|
312 |
|
|
showdigit(3) => flash,
|
313 |
|
|
showdigit(2) => flash,
|
314 |
|
|
showdigit(1) => flash,
|
315 |
|
|
showdigit(0) => flash,
|
316 |
|
|
showdot => led_bus(19 downto 16),
|
317 |
|
|
showsegments => '1',
|
318 |
|
|
-- outputs
|
319 |
|
|
anode => AN,
|
320 |
|
|
segment(6 downto 0) => A_TO_G(6 downto 0),
|
321 |
|
|
segment(7) => DOT
|
322 |
|
|
);
|
323 |
|
|
|
324 |
|
|
-- FREQUENCY GENERATOR
|
325 |
|
|
one_sec: clock_divider port map
|
326 |
|
|
(
|
327 |
|
|
clock => CLK,
|
328 |
|
|
reset => Reset,
|
329 |
|
|
slow(11) => freq1, -- 1Hz
|
330 |
|
|
slow(10) => freq2, -- 2Hz
|
331 |
|
|
slow(9) => freq4, -- 4Hz
|
332 |
|
|
slow(8) => freq8, -- 8Hz
|
333 |
|
|
slow(7) => freq16, -- 16Hz
|
334 |
|
|
slow(6) => freq32, -- 32Hz
|
335 |
|
|
slow(5) => freq64, -- 64Hz
|
336 |
|
|
slow(4) => freq128, -- 128Hz
|
337 |
|
|
slow(3) => freq256, -- 256Hz
|
338 |
|
|
slow(2) => freq512, -- 512Hz
|
339 |
|
|
slow(1) => freq1k, -- 1024Hz
|
340 |
|
|
slow(0) => freq2k, -- 2048Hz
|
341 |
|
|
baud(7) => freq300,
|
342 |
|
|
baud(6) => freq600,
|
343 |
|
|
baud(5) => freq1200,
|
344 |
|
|
baud(4) => freq2400,
|
345 |
|
|
baud(3) => freq4800,
|
346 |
|
|
baud(2) => freq9600,
|
347 |
|
|
baud(1) => freq19200,
|
348 |
|
|
baud(0) => freq38400,
|
349 |
|
|
fast(4) => freq1M5625,
|
350 |
|
|
fast(3) => freq3M125,
|
351 |
|
|
fast(2) => freq6M25,
|
352 |
|
|
fast(1) => freq12M5,
|
353 |
|
|
fast(0) => freq25M
|
354 |
|
|
);
|
355 |
|
|
|
356 |
|
|
-- DEBOUNCE the 8 switches and 4 buttons
|
357 |
|
|
debouncer_sw: debouncer8channel port map (
|
358 |
|
|
clock => freq256,
|
359 |
|
|
reset => Reset,
|
360 |
|
|
signal_raw => SW,
|
361 |
|
|
signal_debounced => switch
|
362 |
|
|
);
|
363 |
|
|
|
364 |
|
|
debouncer_btn: debouncer8channel port map (
|
365 |
|
|
clock => freq256,
|
366 |
|
|
reset => Reset,
|
367 |
|
|
signal_raw(7 downto 4) => "1111", --PMOD(3 downto 0),
|
368 |
|
|
signal_raw(3 downto 0) => BTN(3 downto 0),
|
369 |
|
|
signal_debounced(7 downto 4) => open,
|
370 |
|
|
signal_debounced(3 downto 0) => button
|
371 |
|
|
);
|
372 |
|
|
|
373 |
|
|
-- Single step by each clock cycle, slow or fast
|
374 |
|
|
ss: clocksinglestepper port map (
|
375 |
|
|
reset => Reset,
|
376 |
|
|
clock0_in => freq2,
|
377 |
|
|
clock1_in => freq2k,
|
378 |
|
|
clock2_in => freq6M25,
|
379 |
|
|
clock3_in => freq12M5,
|
380 |
|
|
clocksel => switch(6 downto 5),
|
381 |
|
|
modesel => switch(7),
|
382 |
|
|
singlestep => button(3),
|
383 |
|
|
clock_out => clock_main
|
384 |
|
|
);
|
385 |
|
|
|
386 |
|
|
-- UART for serial input / output
|
387 |
|
|
sio: UART
|
388 |
|
|
generic map
|
389 |
|
|
(
|
390 |
|
|
--CLK_FREQ => 100e6,
|
391 |
|
|
BAUD_RATE => 57600
|
392 |
|
|
--PARITY_BIT => "even"
|
393 |
|
|
--USE_DEBOUNCER => false
|
394 |
|
|
)
|
395 |
|
|
port map
|
396 |
|
|
(
|
397 |
|
|
CLK => CLK,
|
398 |
|
|
RST => Reset,
|
399 |
|
|
-- UART INTERFACE
|
400 |
|
|
UART_TXD => txd, -- serial transmit data
|
401 |
|
|
UART_RXD => PMOD(4), -- serial receive data
|
402 |
|
|
-- USER DATA INPUT INTERFACE
|
403 |
|
|
DATA_IN => alu_y(7 downto 0),
|
404 |
|
|
DATA_SEND => uart_send,
|
405 |
|
|
BUSY => txd_busy,
|
406 |
|
|
-- USER DATA OUTPUT INTERFACE
|
407 |
|
|
DATA_OUT => rxd_data,
|
408 |
|
|
DATA_VLD => rxd_valid,
|
409 |
|
|
FRAME_ERROR => rxd_error
|
410 |
|
|
);
|
411 |
|
|
|
412 |
|
|
-- KEYBOARD
|
413 |
|
|
kbd: PmodKYPD Port map
|
414 |
|
|
( clk => freq1k,
|
415 |
|
|
reset => reset,
|
416 |
|
|
bcdmode => '0',
|
417 |
|
|
Col(3) => kbd_col(3), --PMOD(0), -- out
|
418 |
|
|
Col(2) => kbd_col(2), --PMOD(1),
|
419 |
|
|
Col(1) => kbd_col(1), --PMOD(2),
|
420 |
|
|
Col(0) => kbd_col(0), --PMOD(3),
|
421 |
|
|
Row(3) => PMOD(4), -- in
|
422 |
|
|
Row(2) => PMOD(5),
|
423 |
|
|
Row(1) => PMOD(6),
|
424 |
|
|
Row(0) => PMOD(7),
|
425 |
|
|
key_code => key_code,
|
426 |
|
|
key_down => key_pulse
|
427 |
|
|
);
|
428 |
|
|
|
429 |
|
|
-- output to PMOD is either keyboard columns or UART TXD
|
430 |
|
|
PMOD(3 downto 0) <= kbd_col(0) & kbd_col(1) & kbd_col(2) & kbd_col(3) when switch(0) = '0' else "111" & txd;
|
431 |
|
|
input_pulse <= key_pulse when switch(0) = '0' else rxd_pulse;
|
432 |
|
|
input_code <= key_code when switch(0) = '0' else rxd_code(3 downto 0);
|
433 |
|
|
|
434 |
|
|
-- convert from 8-bit ASCII to hex
|
435 |
|
|
gethexcode: process(rxd_data, rxd_valid, rxd_error)
|
436 |
|
|
begin
|
437 |
|
|
if (rising_edge(rxd_valid)) then
|
438 |
|
|
if (rxd_error = '1') then
|
439 |
|
|
rxd_code <= "01111";
|
440 |
|
|
else
|
441 |
|
|
case rxd_data is
|
442 |
|
|
when X"30" => rxd_code <= "10000"; -- 0
|
443 |
|
|
when X"31" => rxd_code <= "10001";
|
444 |
|
|
when X"32" => rxd_code <= "10010";
|
445 |
|
|
when X"33" => rxd_code <= "10011";
|
446 |
|
|
when X"34" => rxd_code <= "10100";
|
447 |
|
|
when X"35" => rxd_code <= "10101";
|
448 |
|
|
when X"36" => rxd_code <= "10110";
|
449 |
|
|
when X"37" => rxd_code <= "10111";
|
450 |
|
|
when X"38" => rxd_code <= "11000";
|
451 |
|
|
when X"39" => rxd_code <= "11001"; -- 9
|
452 |
|
|
when X"41" => rxd_code <= "11010"; -- A
|
453 |
|
|
when X"42" => rxd_code <= "11011"; -- B
|
454 |
|
|
when X"43" => rxd_code <= "11100"; -- C
|
455 |
|
|
when X"44" => rxd_code <= "11101"; -- D
|
456 |
|
|
when X"45" => rxd_code <= "11110"; -- E
|
457 |
|
|
when X"46" => rxd_code <= "11011"; -- F
|
458 |
|
|
when X"61" => rxd_code <= "11010"; -- a
|
459 |
|
|
when X"62" => rxd_code <= "11011"; -- b
|
460 |
|
|
when X"63" => rxd_code <= "11100"; -- c
|
461 |
|
|
when X"64" => rxd_code <= "11101"; -- d
|
462 |
|
|
when X"65" => rxd_code <= "11110"; -- e
|
463 |
|
|
when X"66" => rxd_code <= "11111"; -- f
|
464 |
|
|
when others => rxd_code <= "01111";
|
465 |
|
|
end case;
|
466 |
|
|
end if;
|
467 |
|
|
end if;
|
468 |
|
|
end process;
|
469 |
|
|
|
470 |
|
|
-- delay rxd_valid to avoid capturing wrong data when generating pulse
|
471 |
|
|
delayrxdvalue: process(clk, rxd_valid)
|
472 |
|
|
begin
|
473 |
|
|
if (rising_edge(clk)) then
|
474 |
|
|
rxd_valid_delayed <= rxd_valid;
|
475 |
|
|
end if;
|
476 |
|
|
end process;
|
477 |
|
|
|
478 |
|
|
rxd_pulse <= rxd_code(4) when rxd_valid_delayed = '1' else '0';
|
479 |
|
|
|
480 |
|
|
-- store incoming hex chars in either input registers
|
481 |
|
|
keyin: process(input_pulse, input_code)
|
482 |
|
|
begin
|
483 |
|
|
if (rising_edge(input_pulse)) then
|
484 |
|
|
if (button(1) = '1') then
|
485 |
|
|
if (button(0) = '0') then
|
486 |
|
|
arg0 <= arg0(27 downto 0) & input_code;
|
487 |
|
|
else
|
488 |
|
|
arg1 <= arg1(27 downto 0) & input_code;
|
489 |
|
|
end if;
|
490 |
|
|
end if;
|
491 |
|
|
end if;
|
492 |
|
|
end process;
|
493 |
|
|
|
494 |
|
|
-- Mini CPU to execute find prime numbers microcode
|
495 |
|
|
|
496 |
|
|
-- This weird logic is added to save on uInstruction count as it allows to trigger "send" signal for UART in one clock cycle
|
497 |
|
|
-- and wait for the readyness in the same cycle. Otherwise 2 would be required. Note that the clock is high frequency for this to work.
|
498 |
|
|
triggersend: process(reset, freq25M, u_uart, uIP)
|
499 |
|
|
begin
|
500 |
|
|
if (reset = '1') then
|
501 |
|
|
send_previous <= X"FF";
|
502 |
|
|
send_current <= X"FF";
|
503 |
|
|
else
|
504 |
|
|
if (rising_edge(freq25M) and u_uart = '1') then
|
505 |
|
|
send_previous <= send_current;
|
506 |
|
|
send_current <= uIP;
|
507 |
|
|
end if;
|
508 |
|
|
end if;
|
509 |
|
|
end process;
|
510 |
|
|
|
511 |
|
|
uart_send <= '0' when send_previous = send_current else '1';
|
512 |
|
|
|
513 |
|
|
-- condition codes used by the sequencer
|
514 |
|
|
with u_condselect select
|
515 |
|
|
condition <= button(2) when cond_buttonstart,
|
516 |
|
|
txd_busy when cond_uartbusy,
|
517 |
|
|
alu_c and not alu_z when cond_alugreaterthan,
|
518 |
|
|
not alu_c when cond_alulessthan,
|
519 |
|
|
sm_ready when cond_muldivready,
|
520 |
|
|
alu_z when cond_aluzero,
|
521 |
|
|
sm_error when cond_muldiverror,
|
522 |
|
|
'0' when cond_false,
|
523 |
|
|
not txd_busy when cond_uartready,
|
524 |
|
|
i_bcdready when cond_ibcdready,
|
525 |
|
|
n_bcdready when cond_nbcdready,
|
526 |
|
|
alu_c when cond_alugreaterorequal,
|
527 |
|
|
not sm_ready when cond_muldivnotready,
|
528 |
|
|
not alu_z when cond_alunotzero,
|
529 |
|
|
not sm_error when cond_muldivok,
|
530 |
|
|
'1' when others;
|
531 |
|
|
|
532 |
|
|
-- contains the prime number finding algorithm. See "findprimes.bs2" Basic Stamp program for similar one.
|
533 |
|
|
microcode: rom32x32 Port map (
|
534 |
|
|
nCS => '0',
|
535 |
|
|
a => uIP(4 downto 0),
|
536 |
|
|
d => uInstruction
|
537 |
|
|
);
|
538 |
|
|
|
539 |
|
|
cu: sequencer Port map (
|
540 |
|
|
reset => reset,
|
541 |
|
|
clk => clock_main,
|
542 |
|
|
operation => u_opsequence,
|
543 |
|
|
condition => condition,
|
544 |
|
|
directvalue => u_value,
|
545 |
|
|
uIP => uIP
|
546 |
|
|
);
|
547 |
|
|
|
548 |
|
|
with u_muxa select
|
549 |
|
|
alu_a <= X"0000" when muxa_zero,
|
550 |
|
|
m when muxa_m,
|
551 |
|
|
arg0(15 downto 0) when muxa_arg0,
|
552 |
|
|
n when muxa_n,
|
553 |
|
|
prod_l when muxa_prod,
|
554 |
|
|
i_bcd(15 downto 0) when muxa_ibcd,
|
555 |
|
|
X"00" & n_bcd(23 downto 16) when muxa_nbcdh,
|
556 |
|
|
n_bcd(15 downto 0) when others; -- nbcdl
|
557 |
|
|
|
558 |
|
|
with u_muxb select
|
559 |
|
|
alu_b <= u_value(7) & u_value(7) & u_value(7) & u_value(7) & u_value(7) & u_value(7) & u_value(7) & u_value(7) & u_value when muxb_const,
|
560 |
|
|
m when muxb_m,
|
561 |
|
|
X"0002" when muxb_two,
|
562 |
|
|
n when muxb_n,
|
563 |
|
|
X"0004" when muxb_four,
|
564 |
|
|
i when muxb_i,
|
565 |
|
|
remainder when muxb_modulo,
|
566 |
|
|
arg1(15 downto 0) when others;
|
567 |
|
|
|
568 |
|
|
alu: alu_with_hex2ascii Port map (
|
569 |
|
|
a => alu_a,
|
570 |
|
|
b => alu_b,
|
571 |
|
|
bcdmode => '1',
|
572 |
|
|
operation => u_alu,
|
573 |
|
|
carry_in => u_ci,
|
574 |
|
|
carry_out => alu_c,
|
575 |
|
|
zero => alu_z,
|
576 |
|
|
y => alu_y
|
577 |
|
|
);
|
578 |
|
|
|
579 |
|
|
update_n: process(clock_main, u_n)
|
580 |
|
|
begin
|
581 |
|
|
if (rising_edge(clock_main)) then
|
582 |
|
|
if (u_n = '1') then
|
583 |
|
|
n <= alu_y;
|
584 |
|
|
u_n2bcdstart <= '1'; -- HACKHACK: this signals should be obviously driven by ucode column!
|
585 |
|
|
else
|
586 |
|
|
u_n2bcdstart <= '0'; -- HACKHACK: this signals should be obviously driven by ucode column!
|
587 |
|
|
end if;
|
588 |
|
|
end if;
|
589 |
|
|
end process;
|
590 |
|
|
|
591 |
|
|
update_i: process(clock_main, u_i)
|
592 |
|
|
begin
|
593 |
|
|
if (rising_edge(clock_main)) then
|
594 |
|
|
if (u_i = '1') then
|
595 |
|
|
i <= alu_y;
|
596 |
|
|
u_i2bcdstart <= '1'; -- HACKHACK: this signals should be obviously driven by ucode column!
|
597 |
|
|
else
|
598 |
|
|
u_i2bcdstart <= '0'; -- HACKHACK: this signals should be obviously driven by ucode column!
|
599 |
|
|
end if;
|
600 |
|
|
end if;
|
601 |
|
|
end process;
|
602 |
|
|
|
603 |
|
|
update_m: process(clock_main, u_m)
|
604 |
|
|
begin
|
605 |
|
|
if (rising_edge(clock_main) and u_m = '1') then
|
606 |
|
|
m <= alu_y;
|
607 |
|
|
end if;
|
608 |
|
|
end process;
|
609 |
|
|
|
610 |
|
|
-- drive multiplier either from microcode or manual input
|
611 |
|
|
sm_control <= button(2) & switch(3 downto 1) when switch(4) = '0' else u_multdiv & u_mode & '0';
|
612 |
|
|
sm_input0h <= arg0(31 downto 16) when switch(4) = '0' else X"0000";
|
613 |
|
|
sm_input0l <= arg0(15 downto 0) when switch(4) = '0' else alu_y;
|
614 |
|
|
sm_input1 <= arg1(15 downto 0) when switch(4) = '0' else m;
|
615 |
|
|
|
616 |
|
|
sm: signedmultiplier port map (
|
617 |
|
|
reset => Reset,
|
618 |
|
|
clk => clock_main,
|
619 |
|
|
start => sm_control(3),
|
620 |
|
|
mode => sm_control(2 downto 1),
|
621 |
|
|
dividend32 => sm_control(0),
|
622 |
|
|
arg0h => sm_input0h,
|
623 |
|
|
arg0l => sm_input0l, -- fac0 or dividend
|
624 |
|
|
arg1 => sm_input1, -- fac1 or divisor
|
625 |
|
|
result => result,
|
626 |
|
|
ready => sm_ready,
|
627 |
|
|
error => sm_error,
|
628 |
|
|
zero => sm_zero,
|
629 |
|
|
sign => sm_sign,
|
630 |
|
|
debug => led_bus(19 downto 16)
|
631 |
|
|
);
|
632 |
|
|
|
633 |
|
|
i2bcd: bin2bcd Port map (
|
634 |
|
|
reset => Reset,
|
635 |
|
|
clk => clock_main,
|
636 |
|
|
start => u_i2bcdstart,
|
637 |
|
|
bin => i,
|
638 |
|
|
ready => i_bcdready,
|
639 |
|
|
bcd => i_bcd,
|
640 |
|
|
debug => open
|
641 |
|
|
);
|
642 |
|
|
|
643 |
|
|
n2bcd: bin2bcd Port map (
|
644 |
|
|
reset => Reset,
|
645 |
|
|
clk => clock_main,
|
646 |
|
|
start => u_n2bcdstart,
|
647 |
|
|
bin => n,
|
648 |
|
|
ready => n_bcdready,
|
649 |
|
|
bcd => n_bcd,
|
650 |
|
|
debug => open
|
651 |
|
|
);
|
652 |
|
|
end;
|