diff options
| author | Clifford Wolf <clifford@clifford.at> | 2014-07-17 16:49:23 +0200 | 
|---|---|---|
| committer | Clifford Wolf <clifford@clifford.at> | 2014-07-17 16:49:23 +0200 | 
| commit | 9b183539af4adf7d2a127042ca384806c7e73367 (patch) | |
| tree | 8fcf063d371ce20fa33eba7d60f6de5ab5bb9fa1 | |
| parent | f1ca93a0a37a4e5f7188af21d2696219329fadfd (diff) | |
| download | yosys-9b183539af4adf7d2a127042ca384806c7e73367.tar.gz yosys-9b183539af4adf7d2a127042ca384806c7e73367.tar.bz2 yosys-9b183539af4adf7d2a127042ca384806c7e73367.zip | |
Implemented dynamic bit-/part-select for memory writes
| -rw-r--r-- | frontends/ast/simplify.cc | 28 | ||||
| -rw-r--r-- | tests/simple/memory.v | 41 | 
2 files changed, 66 insertions, 3 deletions
| diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index eee5a7b39..f819b2506 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1159,7 +1159,7 @@ skip_dynamic_range_lvalue_expansion:;  		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";  		if (type == AST_ASSIGN_EQ) -			log("Warining: Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", +			log("Warning: Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",  					filename.c_str(), linenum);  		int mem_width, mem_size, addr_bits; @@ -1230,7 +1230,31 @@ skip_dynamic_range_lvalue_expansion:;  			}  			else  			{ -				log_error("Writing to memories with dynamic bit- or part-select is not supported yet at %s:%d.\n", filename.c_str(), linenum); +				AstNode *the_range = children[0]->children[1]; +				AstNode *left_at_zero_ast = the_range->children[0]->clone(); +				AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone(); +				AstNode *offset_ast = right_at_zero_ast->clone(); + +				while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } +				while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } +				if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) +					log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); +				int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; + +				for (int i = 0; i < mem_width; i++) +					set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0; + +				assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), +						new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone())); +				assign_data->children[0]->str = id_data; + +				assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), +						new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone())); +				assign_en->children[0]->str = id_en; + +				delete left_at_zero_ast; +				delete right_at_zero_ast; +				delete offset_ast;  			}  		}  		else diff --git a/tests/simple/memory.v b/tests/simple/memory.v index 21271b5e2..ae63e8a16 100644 --- a/tests/simple/memory.v +++ b/tests/simple/memory.v @@ -137,7 +137,26 @@ endmodule  // ---------------------------------------------------------- -module test06(input clk, input rst, input [2:0] idx, input [7:0] din, output [7:0] dout); +module test06_sync(input clk, input rst, input [2:0] idx, input [7:0] din, output [7:0] dout); +    (* gentb_constant=0 *) wire rst; +    reg [7:0] test [0:7]; +    integer i; +    always @(posedge clk) begin +        if (rst) begin +            for (i=0; i<8; i=i+1) +                test[i] <= 0; +        end else begin +            test[0][2] <= din[1]; +            test[0][5] <= test[0][2]; +            test[idx][3] <= din[idx]; +            test[idx][6] <= test[idx][2]; +            test[idx][idx] <= !test[idx][idx]; +        end +    end +    assign dout = test[idx]; +endmodule + +module test06_async(input clk, input rst, input [2:0] idx, input [7:0] din, output [7:0] dout);      (* gentb_constant=0 *) wire rst;      reg [7:0] test [0:7];      integer i; @@ -155,3 +174,23 @@ module test06(input clk, input rst, input [2:0] idx, input [7:0] din, output [7:      end      assign dout = test[idx];  endmodule + +// ---------------------------------------------------------- + +module test07(clk, addr, woffset, wdata, rdata); + +input clk; +input [1:0] addr; +input [3:0] wdata; +input [1:0] woffset; +output reg [7:0] rdata; + +reg [7:0] mem [0:3]; + +integer i; +always @(posedge clk) begin +	mem[addr][woffset +: 4] <= wdata; +	rdata <= mem[addr]; +end + +endmodule | 
