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: |
8bb4608b65e61efa1d8ba49758102d98 |
| 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
Changes to cores/dmac/bench/cpp/dmac.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#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.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > | > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > | > > > | > > > > > > > > > > > > > > > > > > > | 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 | module dmac( i_clk, i_reset, | > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > | > > > > > > > > > > > | 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 |