Kestrel-3

Check-in [8bb4608b65]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Very first TileLink exchange (fixed address, fixed size, fixed alignment). Not too difficult so far.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 8bb4608b65e61efa1d8ba49758102d988b21a0a972ce9b22a7c335b52febd4b2
User & Date: kc5tja 2018-06-09 05:20:40.492
Context
2018-06-09
06:11
Support single-cycle execution opportunity. check-in: 9ab58d4df7 user: kc5tja tags: trunk
05:20
Very first TileLink exchange (fixed address, fixed size, fixed alignment). Not too difficult so far. check-in: 8bb4608b65 user: kc5tja tags: trunk
2018-06-08
06:14
WIP: DMAC: First assertion check-in: beaa6900f1 user: kc5tja tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to cores/dmac/bench/cpp/dmac.cpp.
1
2
3






































4
5
6
7
8
9
10
11

12
13
14



15




















16
17


















18



19



















20
21
22
23
24
#include "Vdmac.h"
#include "verilated.h"








































int
main(int argc, char **argv, char **env) {
	Verilated::commandArgs(argc, argv);
	Vdmac *core = new Vdmac;

	// WHEN I reset the DMAC core
	// THEN all valid outputs should be negated.

	core->i_clk = 1;
	core->i_reset = 1;
	core->eval();
























	assert(core->o_a_valid == 0);



















	core->i_clk = 0;



	core->eval();




















	delete core;
	exit(0);
}




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>
|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "Vdmac.h"
#include "verilated.h"


#define A_OPC_PUT_FULL		0
#define A_OPC_PUT_PARTIAL	1
#define A_OPC_GET		4

#define D_OPC_GET_DATA		1


class ClkPulse {
	Vdmac *m_core;

public:

	ClkPulse(Vdmac *core) : m_core(core) {
		core->i_clk = 1;
		core->eval();
	}

	~ClkPulse() {
		m_core->i_clk = 0;
		m_core->eval();
	}
};


void ResetCore(Vdmac *core) {
	core->i_drq = 0;

	core->i_d_valid = 0;

	{
		ClkPulse p(core);
		core->i_reset = 1;
	} {
		ClkPulse p(core);
		core->i_reset = 0;
	}
}

int
main(int argc, char **argv, char **env) {
	Verilated::commandArgs(argc, argv);
	Vdmac *core = new Vdmac;

	// WHEN I reset the DMAC core
	// THEN all valid outputs should be negated.
	{
		ClkPulse p(core);
		core->i_reset = 1;
		core->i_drq = 1;
	} {
		ClkPulse p(core);
		assert(core->o_a_valid == 0);
	}

	// WHEN I issue a request for a single word from memory
	// THEN I expect a new bus cycle to commence by having a_ready asserted for one cycle.
	ResetCore(core);

	{	// Peripheral registers their request for data in this clock cycle.
		ClkPulse p(core);
		core->i_drq = 1;
		assert(!core->o_a_valid);
	}
	{	// DMAC should respond by driving its master bus in this cycle.
		ClkPulse p(core);
		core->i_drq = 0;
		assert(core->o_a_opcode == A_OPC_GET);
		assert(core->o_a_param == 0);
		assert(core->o_a_size == 4);	// By default, we'll fetch 32-bit words
		// We do not expose an a_source field since this will be used
		// only by the message routing fabric.
		assert(core->o_a_address == 0);
		assert(core->o_a_mask == 0x0F);
		assert(core->o_a_valid);

		// Since we're waiting for a response back, make sure that's
		// reflected on the D channel.
		assert(core->o_d_ready);
	}
	{	// Peripheral only requested one unit of data, so master should not be driven in this cycle.
		ClkPulse p(core);
		assert(!core->o_a_valid);
		// But we should continue to wait for the earlier response.
		assert(core->o_d_ready);
	}

	// GIVEN an outstanding request for a word from memory
	// WHEN I receive a response back from memory
	// THEN I will drive the diagnostic LEDs.
	ResetCore(core);

	{
		ClkPulse p(core);
		core->i_drq = 1;
	}
	{
		ClkPulse p(core);
		core->i_drq = 0;
		// Just in case we somehow are being used in a single-cycle system,
		// announce that we're ready for data right *now*.
		assert(core->o_d_ready);
	}
	{
		ClkPulse p(core);
		core->i_d_opcode = D_OPC_GET_DATA;
		core->i_d_param = 0;
		core->i_d_size = 4;
		core->i_d_data = 0xDEADBEEFFEEDFACE;
		core->i_d_error = 0;
		core->i_d_valid = 1;
		assert(core->o_d_ready);
	}
	{
		ClkPulse p(core);
		assert(core->o_leds == 0xCE);
		assert(!core->o_d_ready);
	}

	delete core;
	exit(0);
}

Changes to cores/dmac/rtl/verilog/dmac.v.








1
2
3
4











5









6
7
8
9


10
11


















12














13
14
15
16






17










18
19

20








module dmac(
	i_clk,
	i_reset,












	o_a_valid









);
	input reg i_clk;
	input reg i_reset;



	output reg o_a_valid;



















	always @(posedge i_clk) begin














		if (i_reset) begin
			o_a_valid <= 0;
		end
		else begin






			o_a_valid <= o_a_valid;










		end
	end

endmodule
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>




>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>


>

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
87
88
89
90
91
92
93
94
95
96
97
98
99
`default_nettype none


`define A_OPC_PUT_FULL		3'd0
`define A_OPC_PUT_PARTIAL	3'd1
`define A_OPC_GET		3'd4


module dmac(
	i_clk,
	i_reset,

	i_drq,

	o_leds,

	// Master Link
	//   Channel A
	o_a_opcode,
	o_a_param,
	o_a_size,
	o_a_address,
	o_a_mask,
	o_a_valid,

	//   Channel D
	i_d_opcode,
	i_d_param,
	i_d_size,
	i_d_data,
	i_d_error,
	i_d_valid,
	o_d_ready
);
	input reg i_clk;
	input reg i_reset;

	input reg i_drq;

	output reg [7:0]	o_leds;

	output reg [2:0]	o_a_opcode = `A_OPC_GET;
	output reg [2:0]	o_a_param = 0;
	output reg [3:0]	o_a_size = 4;
	output reg [63:0]	o_a_address = 0;
	output reg [7:0]	o_a_mask = 8'h0F;
	output reg		o_a_valid;

	input  reg [2:0]	i_d_opcode;
	input  reg [2:0]	i_d_param;
	input  reg [3:0]	i_d_size;
	input  reg [63:0]	i_d_data;
	input  reg		i_d_error;
	input  reg		i_d_valid;
	output reg		o_d_ready;


	// When a transfer request has been made, commence one transfer.

	always @(posedge i_clk) begin
		o_a_valid <= 0;

		if (!i_reset && i_drq) begin
			o_a_valid <= 1;
		end
	end

	// When a transfer is in progress, make sure we're ready to receive
	// any response that comes back.  Make sure to negate o_d_ready
	// when we're not looking for more data again.
	
	always @(posedge i_clk) begin
		o_d_ready <= o_d_ready;

		if (i_reset) begin
			o_d_ready <= 0;
		end
		else if (i_drq) begin
			o_d_ready <= 1;
		end
		else if (o_d_ready && i_d_valid) begin
			o_d_ready <= 0;
		end
	end

	// Set the LEDs to the data we received.
	
	always @(posedge i_clk) begin
		o_leds <= o_leds;

		if (i_reset) begin
			o_leds <= 0;
		end
		else if (o_d_ready && i_d_valid) begin
			o_leds <= i_d_data[7:0];
		end
	end

endmodule