readback!
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
|
||||
../export.py test_regblock.rdl
|
||||
|
||||
vlog -sv -suppress 2720 -quiet -f src.f
|
||||
vlog -sv -f vlog_args.f -f src.f
|
||||
vsim -c -quiet tb -do "log -r /*; run -all; exit;"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
addrmap test_regblock {
|
||||
reg my_reg {
|
||||
field { sw=rw; hw=r; anded;} a[8] = 0x10;
|
||||
field { sw=rw; hw=r; ored;} b[8] = 0x20;
|
||||
field { sw=rw; hw=r; swmod;} c[8] = 0x30;
|
||||
//field { sw=rw; hw=r; ored;} b[8] = 0x20;
|
||||
//field { sw=rw; hw=r; swmod;} c[8] = 0x30;
|
||||
};
|
||||
|
||||
my_reg r0 @0x000;
|
||||
my_reg r1 @0x100;
|
||||
my_reg r2 @0x200;
|
||||
//my_reg r0 @0x000;
|
||||
//my_reg r1 @0x100;
|
||||
my_reg r2[112] @0x200 += 8;
|
||||
};
|
||||
|
||||
@@ -8,20 +8,17 @@ module test_regblock (
|
||||
output test_regblock_pkg::test_regblock__out_t hwif_out
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = 32;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// CPU Bus interface logic
|
||||
//--------------------------------------------------------------------------
|
||||
logic cpuif_req;
|
||||
logic cpuif_req_is_wr;
|
||||
logic [ADDR_WIDTH-1:0] cpuif_addr;
|
||||
logic [DATA_WIDTH-1:0] cpuif_wr_data;
|
||||
logic [DATA_WIDTH-1:0] cpuif_wr_bitstrb;
|
||||
logic [10:0] cpuif_addr;
|
||||
logic [31:0] cpuif_wr_data;
|
||||
logic [31:0] cpuif_wr_biten;
|
||||
|
||||
logic cpuif_rd_ack;
|
||||
logic [DATA_WIDTH-1:0] cpuif_rd_data;
|
||||
logic [31:0] cpuif_rd_data;
|
||||
logic cpuif_rd_err;
|
||||
|
||||
logic cpuif_wr_ack;
|
||||
@@ -43,7 +40,7 @@ module test_regblock (
|
||||
is_active <= '1;
|
||||
cpuif_req <= '1;
|
||||
cpuif_req_is_wr <= s_apb.PWRITE;
|
||||
cpuif_addr <= s_apb.PADDR[ADDR_WIDTH-1:0];
|
||||
cpuif_addr <= {s_apb.PADDR[10:2], 2'b0};
|
||||
cpuif_wr_data <= s_apb.PWDATA;
|
||||
end
|
||||
end else begin
|
||||
@@ -54,7 +51,7 @@ module test_regblock (
|
||||
end
|
||||
end
|
||||
end
|
||||
assign cpuif_wr_bitstrb = '0;
|
||||
assign cpuif_wr_biten = '1;
|
||||
|
||||
// Response
|
||||
assign s_apb.PREADY = cpuif_rd_ack | cpuif_wr_ack;
|
||||
@@ -66,20 +63,18 @@ module test_regblock (
|
||||
// Address Decode
|
||||
//--------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
logic r0;
|
||||
logic r1;
|
||||
logic r2;
|
||||
logic r2[112];
|
||||
} decoded_reg_strb_t;
|
||||
decoded_reg_strb_t decoded_reg_strb;
|
||||
logic decoded_req;
|
||||
logic decoded_req_is_wr;
|
||||
logic [DATA_WIDTH-1:0] decoded_wr_data;
|
||||
logic [DATA_WIDTH-1:0] decoded_wr_bitstrb;
|
||||
logic [31:0] decoded_wr_data;
|
||||
logic [31:0] decoded_wr_biten;
|
||||
|
||||
always_comb begin
|
||||
decoded_reg_strb.r0 = cpuif_req & (cpuif_addr == 'h0);
|
||||
decoded_reg_strb.r1 = cpuif_req & (cpuif_addr == 'h100);
|
||||
decoded_reg_strb.r2 = cpuif_req & (cpuif_addr == 'h200);
|
||||
for(int i0=0; i0<112; i0++) begin
|
||||
decoded_reg_strb.r2[i0] = cpuif_req & (cpuif_addr == 'h200 + i0*'h8);
|
||||
end
|
||||
end
|
||||
|
||||
// Writes are always granted with no error response
|
||||
@@ -90,7 +85,7 @@ module test_regblock (
|
||||
assign decoded_req = cpuif_req;
|
||||
assign decoded_req_is_wr = cpuif_req_is_wr;
|
||||
assign decoded_wr_data = cpuif_wr_data;
|
||||
assign decoded_wr_bitstrb = cpuif_wr_bitstrb;
|
||||
assign decoded_wr_biten = cpuif_wr_biten;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Field logic
|
||||
@@ -101,262 +96,64 @@ module test_regblock (
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} a;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} b;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} c;
|
||||
} r0;
|
||||
struct {
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} a;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} b;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} c;
|
||||
} r1;
|
||||
struct {
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} a;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} b;
|
||||
struct {
|
||||
logic [7:0] next;
|
||||
logic load_next;
|
||||
} c;
|
||||
} r2;
|
||||
} r2[112];
|
||||
} field_combo_t;
|
||||
field_combo_t field_combo;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
logic [7:0] a;
|
||||
logic [7:0] b;
|
||||
logic [7:0] c;
|
||||
} r0;
|
||||
struct {
|
||||
logic [7:0] a;
|
||||
logic [7:0] b;
|
||||
logic [7:0] c;
|
||||
} r1;
|
||||
struct {
|
||||
logic [7:0] a;
|
||||
logic [7:0] b;
|
||||
logic [7:0] c;
|
||||
} r2;
|
||||
} r2[112];
|
||||
} field_storage_t;
|
||||
field_storage_t field_storage;
|
||||
|
||||
// Field: test_regblock.r0.a
|
||||
always_comb begin
|
||||
field_combo.r0.a.next = field_storage.r0.a;
|
||||
field_combo.r0.a.load_next = '0;
|
||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r0.a.next = decoded_wr_data[7:0];
|
||||
field_combo.r0.a.load_next = '1;
|
||||
for(genvar i0=0; i0<112; i0++) begin
|
||||
// Field: test_regblock.r2[].a
|
||||
always_comb begin
|
||||
field_combo.r2[i0].a.next = field_storage.r2[i0].a;
|
||||
field_combo.r2[i0].a.load_next = '0;
|
||||
if(decoded_reg_strb.r2[i0] && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r2[i0].a.next = decoded_wr_data[7:0];
|
||||
field_combo.r2[i0].a.load_next = '1;
|
||||
end
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r0.a <= 'h10;
|
||||
end else if(field_combo.r0.a.load_next) begin
|
||||
field_storage.r0.a <= field_combo.r0.a.next;
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r2[i0].a <= 'h10;
|
||||
end else if(field_combo.r2[i0].a.load_next) begin
|
||||
field_storage.r2[i0].a <= field_combo.r2[i0].a.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r2[i0].a.value = field_storage.r2[i0].a;
|
||||
assign hwif_out.r2[i0].a.anded = &(field_storage.r2[i0].a);
|
||||
end
|
||||
assign hwif_out.r0.a.value = field_storage.r0.a;
|
||||
assign hwif_out.r0.a.anded = &(field_storage.r0.a);
|
||||
// Field: test_regblock.r0.b
|
||||
always_comb begin
|
||||
field_combo.r0.b.next = field_storage.r0.b;
|
||||
field_combo.r0.b.load_next = '0;
|
||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r0.b.next = decoded_wr_data[15:8];
|
||||
field_combo.r0.b.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r0.b <= 'h20;
|
||||
end else if(field_combo.r0.b.load_next) begin
|
||||
field_storage.r0.b <= field_combo.r0.b.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r0.b.value = field_storage.r0.b;
|
||||
assign hwif_out.r0.b.ored = |(field_storage.r0.b);
|
||||
// Field: test_regblock.r0.c
|
||||
always_comb begin
|
||||
field_combo.r0.c.next = field_storage.r0.c;
|
||||
field_combo.r0.c.load_next = '0;
|
||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r0.c.next = decoded_wr_data[23:16];
|
||||
field_combo.r0.c.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r0.c <= 'h30;
|
||||
end else if(field_combo.r0.c.load_next) begin
|
||||
field_storage.r0.c <= field_combo.r0.c.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r0.c.value = field_storage.r0.c;
|
||||
assign hwif_out.r0.c.swmod = decoded_reg_strb.r0 && decoded_req_is_wr;
|
||||
// Field: test_regblock.r1.a
|
||||
always_comb begin
|
||||
field_combo.r1.a.next = field_storage.r1.a;
|
||||
field_combo.r1.a.load_next = '0;
|
||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r1.a.next = decoded_wr_data[7:0];
|
||||
field_combo.r1.a.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r1.a <= 'h10;
|
||||
end else if(field_combo.r1.a.load_next) begin
|
||||
field_storage.r1.a <= field_combo.r1.a.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r1.a.value = field_storage.r1.a;
|
||||
assign hwif_out.r1.a.anded = &(field_storage.r1.a);
|
||||
// Field: test_regblock.r1.b
|
||||
always_comb begin
|
||||
field_combo.r1.b.next = field_storage.r1.b;
|
||||
field_combo.r1.b.load_next = '0;
|
||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r1.b.next = decoded_wr_data[15:8];
|
||||
field_combo.r1.b.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r1.b <= 'h20;
|
||||
end else if(field_combo.r1.b.load_next) begin
|
||||
field_storage.r1.b <= field_combo.r1.b.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r1.b.value = field_storage.r1.b;
|
||||
assign hwif_out.r1.b.ored = |(field_storage.r1.b);
|
||||
// Field: test_regblock.r1.c
|
||||
always_comb begin
|
||||
field_combo.r1.c.next = field_storage.r1.c;
|
||||
field_combo.r1.c.load_next = '0;
|
||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r1.c.next = decoded_wr_data[23:16];
|
||||
field_combo.r1.c.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r1.c <= 'h30;
|
||||
end else if(field_combo.r1.c.load_next) begin
|
||||
field_storage.r1.c <= field_combo.r1.c.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r1.c.value = field_storage.r1.c;
|
||||
assign hwif_out.r1.c.swmod = decoded_reg_strb.r1 && decoded_req_is_wr;
|
||||
// Field: test_regblock.r2.a
|
||||
always_comb begin
|
||||
field_combo.r2.a.next = field_storage.r2.a;
|
||||
field_combo.r2.a.load_next = '0;
|
||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r2.a.next = decoded_wr_data[7:0];
|
||||
field_combo.r2.a.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r2.a <= 'h10;
|
||||
end else if(field_combo.r2.a.load_next) begin
|
||||
field_storage.r2.a <= field_combo.r2.a.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r2.a.value = field_storage.r2.a;
|
||||
assign hwif_out.r2.a.anded = &(field_storage.r2.a);
|
||||
// Field: test_regblock.r2.b
|
||||
always_comb begin
|
||||
field_combo.r2.b.next = field_storage.r2.b;
|
||||
field_combo.r2.b.load_next = '0;
|
||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r2.b.next = decoded_wr_data[15:8];
|
||||
field_combo.r2.b.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r2.b <= 'h20;
|
||||
end else if(field_combo.r2.b.load_next) begin
|
||||
field_storage.r2.b <= field_combo.r2.b.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r2.b.value = field_storage.r2.b;
|
||||
assign hwif_out.r2.b.ored = |(field_storage.r2.b);
|
||||
// Field: test_regblock.r2.c
|
||||
always_comb begin
|
||||
field_combo.r2.c.next = field_storage.r2.c;
|
||||
field_combo.r2.c.load_next = '0;
|
||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
||||
field_combo.r2.c.next = decoded_wr_data[23:16];
|
||||
field_combo.r2.c.load_next = '1;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
field_storage.r2.c <= 'h30;
|
||||
end else if(field_combo.r2.c.load_next) begin
|
||||
field_storage.r2.c <= field_combo.r2.c.next;
|
||||
end
|
||||
end
|
||||
assign hwif_out.r2.c.value = field_storage.r2.c;
|
||||
assign hwif_out.r2.c.swmod = decoded_reg_strb.r2 && decoded_req_is_wr;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Readback
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
logic readback_err;
|
||||
logic readback_done;
|
||||
logic [DATA_WIDTH-1:0] readback_data;
|
||||
logic [DATA_WIDTH-1:0] readback_array[3];
|
||||
logic [31:0] readback_data;
|
||||
|
||||
// Assign readback values to a flattened array
|
||||
logic [31:0] readback_array[112];
|
||||
for(genvar i0=0; i0<112; i0++) begin
|
||||
assign readback_array[i0*1 + 0][7:0] = (decoded_reg_strb.r2[i0] && !decoded_req_is_wr) ? field_storage.r2[i0].a : '0;
|
||||
assign readback_array[i0*1 + 0][31:8] = '0;
|
||||
end
|
||||
|
||||
assign readback_array[0][7:0] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.a : '0;
|
||||
assign readback_array[0][15:8] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.b : '0;
|
||||
assign readback_array[0][23:16] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.c : '0;
|
||||
assign readback_array[0][31:24] = '0;
|
||||
assign readback_array[1][7:0] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.a : '0;
|
||||
assign readback_array[1][15:8] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.b : '0;
|
||||
assign readback_array[1][23:16] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.c : '0;
|
||||
assign readback_array[1][31:24] = '0;
|
||||
assign readback_array[2][7:0] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.a : '0;
|
||||
assign readback_array[2][15:8] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.b : '0;
|
||||
assign readback_array[2][23:16] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.c : '0;
|
||||
assign readback_array[2][31:24] = '0;
|
||||
|
||||
// Reduce the array
|
||||
always_comb begin
|
||||
automatic logic [DATA_WIDTH-1:0] readback_data_var;
|
||||
automatic logic [31:0] readback_data_var;
|
||||
readback_done = decoded_req & ~decoded_req_is_wr;
|
||||
readback_err = '0;
|
||||
|
||||
readback_data_var = '0;
|
||||
for(int i=0; i<3; i++) begin
|
||||
readback_data_var |= readback_array[i];
|
||||
end
|
||||
for(int i=0; i<112; i++) readback_data_var |= readback_array[i];
|
||||
readback_data = readback_data_var;
|
||||
end
|
||||
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
cpuif_rd_ack <= '0;
|
||||
@@ -369,4 +166,5 @@ module test_regblock (
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -1,85 +1,19 @@
|
||||
// TODO: Add a banner
|
||||
package test_regblock_pkg;
|
||||
|
||||
// test_regblock.r0.a
|
||||
// test_regblock.r2[].a
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic anded;
|
||||
} test_regblock__r0__a__out_t;
|
||||
} test_regblock__r2x__a__out_t;
|
||||
|
||||
// test_regblock.r0.b
|
||||
// test_regblock.r2[]
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic ored;
|
||||
} test_regblock__r0__b__out_t;
|
||||
|
||||
// test_regblock.r0.c
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic swmod;
|
||||
} test_regblock__r0__c__out_t;
|
||||
|
||||
// test_regblock.r0
|
||||
typedef struct {
|
||||
test_regblock__r0__a__out_t a;
|
||||
test_regblock__r0__b__out_t b;
|
||||
test_regblock__r0__c__out_t c;
|
||||
} test_regblock__r0__out_t;
|
||||
|
||||
// test_regblock.r1.a
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic anded;
|
||||
} test_regblock__r1__a__out_t;
|
||||
|
||||
// test_regblock.r1.b
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic ored;
|
||||
} test_regblock__r1__b__out_t;
|
||||
|
||||
// test_regblock.r1.c
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic swmod;
|
||||
} test_regblock__r1__c__out_t;
|
||||
|
||||
// test_regblock.r1
|
||||
typedef struct {
|
||||
test_regblock__r1__a__out_t a;
|
||||
test_regblock__r1__b__out_t b;
|
||||
test_regblock__r1__c__out_t c;
|
||||
} test_regblock__r1__out_t;
|
||||
|
||||
// test_regblock.r2.a
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic anded;
|
||||
} test_regblock__r2__a__out_t;
|
||||
|
||||
// test_regblock.r2.b
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic ored;
|
||||
} test_regblock__r2__b__out_t;
|
||||
|
||||
// test_regblock.r2.c
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
logic swmod;
|
||||
} test_regblock__r2__c__out_t;
|
||||
|
||||
// test_regblock.r2
|
||||
typedef struct {
|
||||
test_regblock__r2__a__out_t a;
|
||||
test_regblock__r2__b__out_t b;
|
||||
test_regblock__r2__c__out_t c;
|
||||
} test_regblock__r2__out_t;
|
||||
test_regblock__r2x__a__out_t a;
|
||||
} test_regblock__r2x__out_t;
|
||||
|
||||
// test_regblock
|
||||
typedef struct {
|
||||
test_regblock__r0__out_t r0;
|
||||
test_regblock__r1__out_t r1;
|
||||
test_regblock__r2__out_t r2;
|
||||
test_regblock__r2x__out_t r2[112];
|
||||
} test_regblock__out_t;
|
||||
endpackage
|
||||
9
test/vlog_args.f
Normal file
9
test/vlog_args.f
Normal file
@@ -0,0 +1,9 @@
|
||||
-quiet
|
||||
|
||||
# Free version of ModelSim errors if generate statements are not used.
|
||||
# These have been made optional long ago. Modern versions of SystemVerilog do
|
||||
# not require them.
|
||||
-suppress 2720
|
||||
|
||||
# Ignore warning about vopt-time checking of always_comb/always_latch
|
||||
-suppress 2583
|
||||
@@ -15,7 +15,7 @@ add wave -noupdate /tb/dut/cpuif_req
|
||||
add wave -noupdate /tb/dut/cpuif_req_is_wr
|
||||
add wave -noupdate /tb/dut/cpuif_addr
|
||||
add wave -noupdate /tb/dut/cpuif_wr_data
|
||||
add wave -noupdate /tb/dut/cpuif_wr_bitstrb
|
||||
add wave -noupdate /tb/dut/cpuif_wr_biten
|
||||
add wave -noupdate /tb/dut/cpuif_rd_ack
|
||||
add wave -noupdate /tb/dut/cpuif_rd_data
|
||||
add wave -noupdate /tb/dut/cpuif_rd_err
|
||||
|
||||
Reference in New Issue
Block a user