在 Verilog 中替换 case 语句
Replacing case statement in Verilog
我有一组地址范围从 0x20 到 0x60 的多个寄存器。如果处理器想在任何时间读取这些寄存器中的任何一个,我必须发送相应的寄存器 data.Right 现在我通过指定所有寄存器地址并将寄存器数据分配给数据总线来使用 case 语句。
我们可以在代码行方面做一些简化吗?
例如
always @(posedge clk) begin
if (!fpga_rst) begin
dataout <= 16'd0;
end
else if (!rd_en) begin
case (reg_addr)
0x0012: dataout <= fpga_ver_reg;
0x0014 : dataout <= act0_reg;
0x0016 : dataout <= act1_reg;
0x0018 : dataout <= list0_reg;
0x001A : dataout <=list1_reg;
0x001C : dataout <= dr_reg;
0x001D : dataout <= dr0_reg;
0x001F : dataout <= dr1_reg;
0x0020 : dataout <= dr2_reg;
e.t.c
0x0040 : dataout <= cr2_reg;
end case
正如所写,我不这么认为。由于每个寄存器都有不同的名称,因此不能将它们组合成一个循环。
如果您的寄存器是数组的一部分并且都具有相同的名称,您可以执行如下操作:
integer i;
parameter BASEADDR=0x20;
reg [15:0] myregs [31:0];
always@(posedge clk) begin
... // some reset
for (i=0; i<32; i=i+1) begin
if (reg_addr == BASEADDR + i*2)
dataout <= myregs[i];
end
end
就代码行而言,这可能会更短,但您将失去为每个寄存器指定自己的名称的优势,这可能会提高可读性或对电路的理解。
或者,您可以这样做,然后将每个 myregs
分配给一个 'named' reg(如 dr2_reg
),但这实际上不会使您的代码更短,只把长度移到另一个地方。
您也可以通过执行以下操作来平分差额:
integer i;
parameter DREGBASEADDR=0x1C;
parameter CREGBASEADDR=0x36;
...
reg [15:0] dregs [2:0];
reg [15:0] cregs [2:0];
...
always@(posedge clk) begin
... // some reset
for (i=0; i<3; i=i+1) begin
if (reg_addr == CREGBASEADDR + i*2)
dataout <= cregs[i];
else if (reg_addr == DBASEREGADDR + i*2)
dataout <= dregs[i];
...
end
end
如果您可以将一些名称组合成数组,则可能会更短,具体取决于组的大小。
我有一组地址范围从 0x20 到 0x60 的多个寄存器。如果处理器想在任何时间读取这些寄存器中的任何一个,我必须发送相应的寄存器 data.Right 现在我通过指定所有寄存器地址并将寄存器数据分配给数据总线来使用 case 语句。
我们可以在代码行方面做一些简化吗?
例如
always @(posedge clk) begin
if (!fpga_rst) begin
dataout <= 16'd0;
end
else if (!rd_en) begin
case (reg_addr)
0x0012: dataout <= fpga_ver_reg;
0x0014 : dataout <= act0_reg;
0x0016 : dataout <= act1_reg;
0x0018 : dataout <= list0_reg;
0x001A : dataout <=list1_reg;
0x001C : dataout <= dr_reg;
0x001D : dataout <= dr0_reg;
0x001F : dataout <= dr1_reg;
0x0020 : dataout <= dr2_reg;
e.t.c
0x0040 : dataout <= cr2_reg;
end case
正如所写,我不这么认为。由于每个寄存器都有不同的名称,因此不能将它们组合成一个循环。
如果您的寄存器是数组的一部分并且都具有相同的名称,您可以执行如下操作:
integer i;
parameter BASEADDR=0x20;
reg [15:0] myregs [31:0];
always@(posedge clk) begin
... // some reset
for (i=0; i<32; i=i+1) begin
if (reg_addr == BASEADDR + i*2)
dataout <= myregs[i];
end
end
就代码行而言,这可能会更短,但您将失去为每个寄存器指定自己的名称的优势,这可能会提高可读性或对电路的理解。
或者,您可以这样做,然后将每个 myregs
分配给一个 'named' reg(如 dr2_reg
),但这实际上不会使您的代码更短,只把长度移到另一个地方。
您也可以通过执行以下操作来平分差额:
integer i;
parameter DREGBASEADDR=0x1C;
parameter CREGBASEADDR=0x36;
...
reg [15:0] dregs [2:0];
reg [15:0] cregs [2:0];
...
always@(posedge clk) begin
... // some reset
for (i=0; i<3; i=i+1) begin
if (reg_addr == CREGBASEADDR + i*2)
dataout <= cregs[i];
else if (reg_addr == DBASEREGADDR + i*2)
dataout <= dregs[i];
...
end
end
如果您可以将一些名称组合成数组,则可能会更短,具体取决于组的大小。