structを使ってみる。
verilog-95を使っていて。。VHDL羨ましいな~~と指をくわえていたところが1点だけ有った。
VHDLはユーザー定義のデータ型を使用できて合成も出来る。→VHDLにしとけばと思っていたね。。
→SPARC LEON-2のコードにユーザー定義のデータ型が使われていた。。当然合成も出来る。。
VHDLはユーザー定義のデータ型を使用できて合成も出来る。→VHDLにしとけばと思っていたね。。
→SPARC LEON-2のコードにユーザー定義のデータ型が使われていた。。当然合成も出来る。。
めでたくsystemVerilogで強力なデータ型の使用が可能となったので試してみた。
結果。。
union -> Quaruts2駄目。。
packedは使えるので。。とりあえず良し。。
-> modelSim OK!!
例題はご存じtimer_core.sv下記に貼り付けた。
/*
union packed{
logic [1:0] control_reg ;
struct packed {
logic count_en ;
logic intr_clr ;
} control ;
} control_un ;
*/
typedef enum logic [2:0] {
IDLE,
LOAD,
RUN
} state_t ;
typedef struct packed{
logic count_en ;
logic intr_clr ;
} control_t ;
typedef struct {
logic [31:0] count ;
state_t state ;
logic [31:0] c_value ;
logic intr ;
} timer_t ;
module timer_core(interface wb_bus) ;
control_t control ;
timer_t timer ;
logic [31:0] rdat ;
wire clk = wb_bus.clk_i ;
wire nrst = wb_bus.nrst_i ;
wire [31:0] dat_i = wb_bus.dat_i ;
wire we_i = wb_bus.we_i ;
wire stb_count = wb_bus.stb_i == 1'b1 && wb_bus.sel_i == 4'b1111 && wb_bus.adr_i[2] == 1'b0 ;
wire stb_control = wb_bus.stb_i == 1'b1 && wb_bus.sel_i == 4'b1111 && wb_bus.adr_i[2] == 1'b1 ;
assign wb_bus.intr_o = timer.intr == 1'b1 ;
assign wb_bus.dat_o = rdat ;
assign wb_bus.ack_o = 1'b0 ;
always_comb begin
case ({stb_count, stb_control})
2'b10 : rdat = timer.count ;
2'b01 : rdat = {30'h00, control} ;
default : rdat = 32'h0 ;
endcase // case ({stb_count, stb_control})
end
// -- count state -------------------
// - IDLE --> LOAD -> RUN
// - ^ ^ |
// - | +-------+
// - +----------------+
// -
// - IDLE -> LOAD :: control == RUN
// - LOAD -> RUN :: always
// - RUN -> LOAD :: count_end - 1
// - RUN -> IDLE :: control == STOP
// ----------------------------------
always_ff @(posedge clk, negedge nrst) begin
if(nrst == 1'b0) begin
timer.count <= #1 32'hffff_ffff ;
// -- timer state --
timer.state <= #1 IDLE ;
end
else
case (timer.state)
IDLE : begin
timer.count <= #1 32'hffff_ffff ;
// -- timer state --
if(control.count_en == 1'b1)
timer.state <= #1 LOAD ;
else
timer.state <= #1 IDLE ;
end
LOAD : begin
timer.count <= #1 timer.c_value ;
// -- timer state --
timer.state <= #1 RUN ;
end
RUN : begin
timer.count <= timer.count - 1 ;
// -- timer state --
if(control.count_en == 1'b0)
timer.state <= #1 IDLE ;
else if(timer.count == 32'h0000_0001) // -- end of count --
timer.state <= #1 LOAD ;
else
timer.state <= #1 RUN ;
end
default : begin
timer.count <= #1 32'hffff_ffff ;
// -- timer state --
timer.state <= #1 IDLE ;
end
endcase // case (state)
end // always_ff @ (posedge clk, negedge nrst)
// -- count value --
always_ff @(posedge clk, negedge nrst) begin
if(nrst == 1'b0)
timer.c_value <= #1 32'hffff_ffff ;
else if(stb_count == 1'b1 && we_i == 1'b1)
timer.c_value <= #1 dat_i ;
else
timer.c_value <= #1 timer.c_value ;
end
// -- intrrput register --
always_ff @(posedge clk, negedge nrst) begin
if(nrst == 1'b0)
timer.intr <= #1 1'b0 ;
else if(control.intr_clr == 1'b0)
timer.intr <= #1 1'b0 ;
else if(timer.count == 32'h0000_0001)
timer.intr <= #1 1'b1 ;
else
timer.intr <= #1 timer.intr ;
end
// -- control register --
always_ff @(posedge clk, negedge nrst) begin
if(nrst == 1'b0)
control <= #1 0 ;
else if(stb_control == 1'b1 && we_i == 1'b1)
control <= #1 dat_i[1:0] ;
else
control <= #1 control ;
end
endmodule