summaryrefslogtreecommitdiff
path: root/hdl
diff options
context:
space:
mode:
Diffstat (limited to 'hdl')
-rw-r--r--hdl/bin2bcd.sv76
-rw-r--r--hdl/fibseq.sv32
-rw-r--r--hdl/jtag_uart.sv84
-rw-r--r--hdl/ntoa.sv90
-rw-r--r--hdl/top.sv152
-rw-r--r--hdl/utils.svh5
6 files changed, 439 insertions, 0 deletions
diff --git a/hdl/bin2bcd.sv b/hdl/bin2bcd.sv
new file mode 100644
index 0000000..9b1609b
--- /dev/null
+++ b/hdl/bin2bcd.sv
@@ -0,0 +1,76 @@
1`include "utils.svh"
2
3module bin2bcd
4 #( BITS = 8
5 , BASE = 10
6 , BASE_BITS = $clog2(BASE)
7 , DIGITS = 3 // should be ceil[log(2**BITS) base BASE] which is hard to do in Verilog :-(
8 , MAX_SKIP = BITS
9 )
10 ( input bit clk
11 , input bit reset
12
13 , output bit bin_ready
14 , input bit bin_valid `define bin_valid `past(bin_valid)
15 , input bit [BITS-1:0] bin_data `define bin_data `past(bin_data)
16
17 , input bit bcd_ready `define bcd_ready `past(bcd_ready)
18 , output bit bcd_valid
19 , output bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data
20 );
21
22bit bin_b_valid;
23bit [BITS-1:0] bin_b_data;
24
25bit [DIGITS-1:0][BASE_BITS-1:0] bcd;
26
27bit [$clog2(BITS):0] work;
28
29always_ff @(posedge clk) begin
30 if (reset) begin
31 bin_ready = 0;
32 bcd_valid = 0;
33 bin_b_valid = 0;
34 end else begin
35 if (bin_ready && `bin_valid) begin
36 bin_b_valid = 1;
37 bin_b_data = `bin_data;
38 bcd = 0;
39 work = BITS;
40 for (int i = 0; i < BITS && i < MAX_SKIP; ++i) begin
41 if (bin_b_data[BITS-1]) break;
42 bin_b_data = { bin_b_data[BITS-2:0], 1'b0 };
43 work = work - 1;
44 end
45 end
46
47 if (bin_b_valid && work != 0) begin
48 automatic bit carry = bin_b_data[BITS-1];
49 for (int i = 0; i < DIGITS; ++i) begin
50 {carry, bcd[i]} = {bcd[i], carry};
51 if ({carry, bcd[i]} >= BASE) begin
52 // verilator lint_off WIDTH
53 bcd[i] = {carry, bcd[i]} - BASE;
54 // verilator lint_on WIDTH
55 carry = 1;
56 end
57 end
58 assert(!carry);
59
60 bin_b_data = bin_b_data << 1;
61
62 work = work - 1;
63 end
64
65 if (`bcd_ready) bcd_valid = 0;
66 if (!bcd_valid && bin_b_valid && work == 0) begin
67 bcd_valid = 1;
68 bcd_data = bcd;
69 bin_b_valid = 0;
70 end
71
72 bin_ready = !bin_b_valid;
73 end
74end
75
76endmodule
diff --git a/hdl/fibseq.sv b/hdl/fibseq.sv
new file mode 100644
index 0000000..752c0b6
--- /dev/null
+++ b/hdl/fibseq.sv
@@ -0,0 +1,32 @@
1`include "utils.svh"
2
3module fibseq
4 #( BITS = 8
5 )
6 ( input bit clk
7 , input bit reset
8
9 , input bit ready `define ready `past(ready)
10 , output bit valid
11 , output bit [BITS-1:0] data
12 );
13
14bit [BITS-1:0] a;
15bit [BITS-1:0] b;
16
17always_ff @(posedge clk) begin
18 if (reset) begin
19 valid = 0;
20 a = 0;
21 b = 1;
22 end else begin
23 if (`ready) valid = 0;
24 if (!valid) begin
25 valid = 1;
26 data = a;
27 {a, b} = {b, a + b};
28 end
29 end
30end
31
32endmodule
diff --git a/hdl/jtag_uart.sv b/hdl/jtag_uart.sv
new file mode 100644
index 0000000..eb0bc11
--- /dev/null
+++ b/hdl/jtag_uart.sv
@@ -0,0 +1,84 @@
1`include "utils.svh"
2
3module jtag_uart
4 #( INSTANCE = 0
5
6 , RX_FIFO_BITS = 6
7 , TX_FIFO_BITS = 6
8 )
9 ( input bit clk
10 , input bit reset
11
12 , input bit rx_ready `define rx_ready `past(rx_ready)
13 , output bit rx_valid
14 , output bit [7:0] rx_data
15
16 , output bit tx_ready
17 , input bit tx_valid `define tx_valid `past(tx_valid)
18 , input bit [7:0] tx_data `define tx_data `past(tx_data)
19 );
20
21`ifdef SYNTHESIS
22
23alt_jtag_atlantic
24 #( .INSTANCE_ID(INSTANCE)
25 , .LOG2_RXFIFO_DEPTH(RX_FIFO_BITS)
26 , .LOG2_TXFIFO_DEPTH(TX_FIFO_BITS)
27 , .SLD_AUTO_INSTANCE_INDEX("NO")
28 ) real_jtag
29 ( .clk(clk)
30 , .rst_n(!reset)
31 , .r_dat(tx_data)
32 , .r_val(tx_valid)
33 , .r_ena(tx_ready)
34 , .t_dat(rx_data)
35 , .t_dav(rx_ready)
36 , .t_ena(rx_valid)
37 );
38
39`else
40
41bit [7:0] sim_rx_rom [0:(1<<16)-1];
42initial $readmemh("mem/jtag_uart.hex", sim_rx_rom);
43
44bit [15:0] sim_rx_addr;
45
46bit tx_b_valid;
47bit [7:0] tx_b_data;
48
49always_ff @(posedge clk) begin
50 if (reset) begin
51 rx_valid = 0;
52 tx_ready = 0;
53 sim_rx_addr = 0;
54 tx_b_valid = 0;
55 end else begin
56 automatic bit [7:0] sim_rx_data = sim_rx_rom[sim_rx_addr];
57
58 // RX logic
59 if (`rx_ready) rx_valid = 0;
60 if (!rx_valid && (sim_rx_data != 0)) begin
61`ifdef JTAG_UART_LOCAL_ECHO
62 $write("%s", sim_rx_data);
63`endif
64 rx_valid = 1;
65 rx_data = sim_rx_data;
66 sim_rx_addr = sim_rx_addr + 1;
67 end
68
69 // TX logic
70 if (tx_ready && `tx_valid) begin
71 tx_b_valid = 1;
72 tx_b_data = `tx_data;
73 end
74 if (tx_b_valid) begin
75 $write("%s", tx_b_data);
76 tx_b_valid = 0;
77 end
78 tx_ready = !tx_b_valid;
79 end
80end
81
82`endif
83
84endmodule
diff --git a/hdl/ntoa.sv b/hdl/ntoa.sv
new file mode 100644
index 0000000..6da1baf
--- /dev/null
+++ b/hdl/ntoa.sv
@@ -0,0 +1,90 @@
1`include "utils.svh"
2
3module ntoa
4 #( BITS = 8
5 , BASE = 10
6 , BASE_BITS = $clog2(BASE)
7 , DIGITS = 3 // should be ceil[log(2**BITS) base BASE] which is hard to do in Verilog :-(
8 )
9 ( input bit clk
10 , input bit reset
11
12 , output bit n_ready
13 , input bit n_valid `define n_valid `past(n_valid)
14 , input bit [BITS-1:0] n_data `define n_data `past(n_data)
15
16 , input bit a_ready `define a_ready `past(a_ready)
17 , output bit a_valid
18 , output bit [7:0] a_data
19 );
20
21bit bcd_ready;
22bit bcd_valid;
23bit [DIGITS-1:0][BASE_BITS-1:0] bcd_data;
24
25bin2bcd
26 #( .BITS(BITS)
27 , .BASE(BASE)
28 , .BASE_BITS(BASE_BITS)
29 , .DIGITS(DIGITS)
30 ) b2b
31 ( .clk(clk)
32 , .reset(reset)
33
34 , .bin_ready(n_ready)
35 , .bin_valid(n_valid)
36 , .bin_data(n_data)
37
38 , .bcd_ready(bcd_ready)
39 , .bcd_valid(bcd_valid) `define bcd_valid `past(bcd_valid)
40 , .bcd_data(bcd_data) `define bcd_data `past(bcd_data)
41 );
42
43bit bcd_b_valid;
44bit [DIGITS-1:0][BASE_BITS-1:0] bcd_b_data;
45
46bit [$clog2(DIGITS):0] work;
47
48always_ff @(posedge clk) begin
49 if (reset) begin
50 a_valid = 0;
51 bcd_ready = 0;
52 bcd_b_valid = 0;
53 end else begin
54 if (bcd_ready && `bcd_valid) begin
55 bcd_b_valid = 1;
56 bcd_b_data = `bcd_data;
57 // verilator lint_off WIDTH
58 work = DIGITS;
59 // verilator lint_on WIDTH
60 for (int i = 0; i < DIGITS - 1; ++i) begin
61 if (bcd_b_data[DIGITS-1] != 0) break;
62 bcd_b_data = { bcd_b_data[DIGITS-2:0], {BASE_BITS{1'b0}} };
63 --work;
64 end
65 end
66
67 if (`a_ready) a_valid = 0;
68 if (!a_valid && bcd_b_valid) begin
69 if (work != 0) begin
70 a_valid = 1;
71 // verilator lint_off WIDTH
72 if (bcd_b_data[DIGITS-1] < 10)
73 a_data = "0" + bcd_b_data[DIGITS-1];
74 else
75 a_data = "a" + bcd_b_data[DIGITS-1] - 10;
76 // verilator lint_off WIDTH
77 bcd_b_data = { bcd_b_data[DIGITS-2:0], {BASE_BITS{1'b0}} };
78 --work;
79 end else begin
80 a_valid = 1;
81 a_data = ",";
82 bcd_b_valid = 0;
83 end
84 end
85
86 bcd_ready = !bcd_b_valid;
87 end
88end
89
90endmodule
diff --git a/hdl/top.sv b/hdl/top.sv
new file mode 100644
index 0000000..33c1fc5
--- /dev/null
+++ b/hdl/top.sv
@@ -0,0 +1,152 @@
1`include "utils.svh"
2
3module top
4 #( FIB_BITS = 16
5 , FIB_BASE = 10
6 , FIB_DIGITS = 5
7
8 , ROM_BITS = 8
9 )
10 ( input bit clk // verilator public
11 , input bit reset_n // verilator public
12 );
13
14bit reset;
15assign reset = !reset_n;
16
17bit [7:0] rom [0:(1<<ROM_BITS)-1];
18initial $readmemh("mem/rom.hex", rom);
19
20bit [ROM_BITS-1:0] addr;
21
22bit rx_ready;
23bit rx_valid;
24bit [7:0] rx_data;
25
26bit tx_ready;
27bit tx_valid;
28bit [7:0] tx_data;
29
30jtag_uart
31 #( .INSTANCE(0)
32 ) uart0
33 ( .clk(clk)
34 , .reset(reset)
35
36 , .rx_ready(rx_ready)
37 , .rx_valid(rx_valid) `define rx_valid `past(rx_valid)
38 , .rx_data(rx_data) `define rx_data `past(rx_data)
39
40 , .tx_ready(tx_ready) `define tx_ready `past(tx_ready)
41 , .tx_valid(tx_valid)
42 , .tx_data(tx_data)
43 );
44
45bit fib_ready;
46bit fib_valid;
47bit [FIB_BITS-1:0] fib_data;
48
49fibseq
50 #( .BITS(FIB_BITS)
51 ) fib
52 ( .clk(clk)
53 , .reset(reset)
54
55 , .ready(fib_ready)
56 , .valid(fib_valid)
57 , .data(fib_data)
58 );
59
60bit fib_a_ready;
61bit fib_a_valid;
62bit [7:0] fib_a_data;
63
64ntoa
65 #( .BITS(FIB_BITS)
66 , .BASE(FIB_BASE)
67 , .DIGITS(FIB_DIGITS)
68 ) fib_ntoa
69 ( .clk(clk)
70 , .reset(reset)
71
72 , .n_ready(fib_ready)
73 , .n_valid(fib_valid)
74 , .n_data(fib_data)
75
76 , .a_ready(fib_a_ready)
77 , .a_valid(fib_a_valid) `define fib_a_valid `past(fib_a_valid)
78 , .a_data(fib_a_data) `define fib_a_data `past(fib_a_data)
79 );
80
81enum
82 { INTRO_ECHO
83 , ECHO
84 , INTRO_FIB
85 , FIB
86 } state;
87
88bit tmp_valid;
89bit [7:0] tmp_data;
90
91always_ff @(posedge clk) begin
92 if (reset) begin
93 addr = 0;
94 rx_ready = 0;
95 tx_valid = 0;
96 fib_a_ready = 0;
97 state = state.first;
98 tmp_valid = 0;
99 end else case (state)
100
101 INTRO_ECHO, INTRO_FIB: begin
102 automatic bit [7:0] data = rom[addr];
103 if (`tx_ready) tx_valid = 0;
104 if (!tx_valid && (data != 0)) begin
105 tx_valid = 1;
106 tx_data = data;
107 ++addr;
108 end else if (data == 0) begin
109 ++addr;
110 state = state.next;
111 end
112 end
113
114 ECHO: begin
115 if (`tx_ready && tx_valid && tx_data == "\n") begin
116 // FIXME race; we aren't going to consume input this cycle, but we might have tmp_valid or rx_ready asserted
117 rx_ready = 0;
118 tx_valid = 0;
119 state = INTRO_FIB;
120 end else begin
121 if (`tx_ready) tx_valid = 0;
122 if (rx_ready && `rx_valid) begin
123 tmp_valid = 1;
124 tmp_data = `rx_data;
125 end
126 if (!tx_valid && tmp_valid) begin
127 tx_valid = 1;
128 tx_data = tmp_data;
129 tmp_valid = 0;
130 end
131 rx_ready = !tmp_valid;
132 end
133 end
134
135 FIB: begin
136 if (`tx_ready) tx_valid = 0;
137 if (fib_a_ready && `fib_a_valid) begin
138 tmp_valid = 1;
139 tmp_data = `fib_a_data;
140 end
141 if (!tx_valid && tmp_valid) begin
142 tx_valid = 1;
143 tx_data = tmp_data;
144 tmp_valid = 0;
145 end
146 fib_a_ready = !tmp_valid;
147 end
148
149 endcase
150end
151
152endmodule
diff --git a/hdl/utils.svh b/hdl/utils.svh
new file mode 100644
index 0000000..ddba543
--- /dev/null
+++ b/hdl/utils.svh
@@ -0,0 +1,5 @@
1`ifdef SYNTHESIS
2`define past(x) x
3`else
4`define past(x) $past(x)
5`endif