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