-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathperipheral.v
More file actions
86 lines (67 loc) · 3.41 KB
/
Copy pathperipheral.v
File metadata and controls
86 lines (67 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
* Copyright (c) 2025 Your Name
* SPDX-License-Identifier: Apache-2.0
*/
`default_nettype none
// Change the name of this module to something that reflects its functionality and includes your name for uniqueness
// For example tqvp_yourname_spi for an SPI peripheral.
// Then edit tt_wrapper.v line 41 and change tqvp_example to your chosen module name.
module tqvp_example (
input clk, // Clock - the TinyQV project clock is normally set to 64MHz.
input rst_n, // Reset_n - low to reset.
input [7:0] ui_in, // The input PMOD, always available. Note that ui_in[7] is normally used for UART RX.
// The inputs are synchronized to the clock, note this will introduce 2 cycles of delay on the inputs.
output [7:0] uo_out, // The output PMOD. Each wire is only connected if this peripheral is selected.
// Note that uo_out[0] is normally used for UART TX.
input [5:0] address, // Address within this peripheral's address space
input [31:0] data_in, // Data in to the peripheral, bottom 8, 16 or all 32 bits are valid on write.
// Data read and write requests from the TinyQV core.
input [1:0] data_write_n, // 11 = no write, 00 = 8-bits, 01 = 16-bits, 10 = 32-bits
input [1:0] data_read_n, // 11 = no read, 00 = 8-bits, 01 = 16-bits, 10 = 32-bits
output [31:0] data_out, // Data out from the peripheral, bottom 8, 16 or all 32 bits are valid on read when data_ready is high.
output data_ready,
output user_interrupt // Dedicated interrupt request for this peripheral
);
// Implement a 32-bit read/write register at address 0
reg [31:0] example_data;
always @(posedge clk) begin
if (!rst_n) begin
example_data <= 0;
end else begin
if (address == 6'h0) begin
if (data_write_n != 2'b11) example_data[7:0] <= data_in[7:0];
if (data_write_n[1] != data_write_n[0]) example_data[15:8] <= data_in[15:8];
if (data_write_n == 2'b10) example_data[31:16] <= data_in[31:16];
end
end
end
// The bottom 8 bits of the stored data are added to ui_in and output to uo_out.
assign uo_out = example_data[7:0] + ui_in;
// Address 0 reads the example data register.
// Address 4 reads ui_in
// All other addresses read 0.
assign data_out = (address == 6'h0) ? example_data :
(address == 6'h4) ? {24'h0, ui_in} :
32'h0;
// All reads complete in 1 clock
assign data_ready = 1;
// User interrupt is generated on rising edge of ui_in[6], and cleared by writing a 1 to the low bit of address 8.
reg example_interrupt;
reg last_ui_in_6;
always @(posedge clk) begin
if (!rst_n) begin
example_interrupt <= 0;
end
if (ui_in[6] && !last_ui_in_6) begin
example_interrupt <= 1;
end else if (address == 6'h8 && data_write_n != 2'b11 && data_in[0]) begin
example_interrupt <= 0;
end
last_ui_in_6 <= ui_in[6];
end
assign user_interrupt = example_interrupt;
// List all unused inputs to prevent warnings
// data_read_n is unused as none of our behaviour depends on whether
// registers are being read.
wire _unused = &{data_read_n, 1'b0};
endmodule