chisel 虐我千百遍(一)
前几天想将一个大小端转换的模块转成chisel,感觉挺简单,但真写起来就各种bug。
module EndianCnvt #(parameter NUMLENGTH = 128)(
input [NUMLENGTH-1:0] NumIn,
output [NUMLENGTH-1:0] NumOut
);
localparam BYTENUM = NUMLENGTH/8;
genvar i;
for (i=0; i
一开始就是简单直译,但会保存,因为UInt类型不能切片赋值,在一点在官网cookbook其实已经说了,是我没认真看~
class EndianCnvt (NUMLENGTH :Int)extends Module{
val io = IO(new Bundle {
val NumIn = Input(UInt(NUMLENGTH.W))
val NumOut= Output(UInt(NUMLENGTH.W))
})
val BYENUM = NUMLENGTH>>3
val temp = Wire(Vec(BYENUM,UInt(8.W)))
for (i <- 0 until BYENUM){
io.NumOut[(i+1)*8-1:i*8] := io.NumIn((BYENUM-i)*8-1,(BYENUM-i-1)*8)//UInt不能切片赋值
}
}
需要先转换类型才能赋值:
class EndianCnvt (NUMLENGTH :Int)extends Module{
val io = IO(new Bundle {
val NumIn = Input(UInt(NUMLENGTH.W))
val NumOut= Output(UInt(NUMLENGTH.W))
})
val BYENUM = NUMLENGTH>>3
val temp = Wire(Vec(BYENUM,UInt(8.W)))//转换成8bit的数组,分别赋值,再转回UInt
for (i <- 0 until BYENUM){
temp(i) := io.NumIn((BYENUM-i)*8-1,(BYENUM-i-1)*8)
}
io.NumOut := temp.asUInt
}
后来大神说可以用reverse的方法,还是很好用的,最后再添加例化模块的apply方法
class EndianCnvt (NUMLENGTH :Int)extends Module{
val io = IO(new Bundle {
val NumIn = Input(UInt(NUMLENGTH.W))
val NumOut= Output(UInt(NUMLENGTH.W))
})
val BYENUM = NUMLENGTH>>3
val temp = io.NumIn.asTypeOf(Vec(BYENUM,UInt(8.W)))
val temp2 = Wire(Vec(BYENUM,UInt(8.W)))
temp2 := temp.reverse //reverse方法,这里必须借助中间变量temp2,不然也会报错
io.NumOut := temp2.asUInt()
}
object EndianCnvt{
def apply(in1:UInt,NUMLENGTH:Int) :UInt={
val inst = Module(new EndianCnvt(NUMLENGTH))
inst.io.NumIn := in1
inst.io.NumOut
}
}
生成的verilog如下:
module EndianCnvt(
input clock,
input reset,
input [127:0] io_NumIn,
output [127:0] io_NumOut
);
wire [7:0] temp_0 = io_NumIn[7:0]; // @[sub_module.scala 32:32]
wire [7:0] temp_1 = io_NumIn[15:8]; // @[sub_module.scala 32:32]
wire [7:0] temp_2 = io_NumIn[23:16]; // @[sub_module.scala 32:32]
wire [7:0] temp_3 = io_NumIn[31:24]; // @[sub_module.scala 32:32]
wire [7:0] temp_4 = io_NumIn[39:32]; // @[sub_module.scala 32:32]
wire [7:0] temp_5 = io_NumIn[47:40]; // @[sub_module.scala 32:32]
wire [7:0] temp_6 = io_NumIn[55:48]; // @[sub_module.scala 32:32]
wire [7:0] temp_7 = io_NumIn[63:56]; // @[sub_module.scala 32:32]
wire [7:0] temp_8 = io_NumIn[71:64]; // @[sub_module.scala 32:32]
wire [7:0] temp_9 = io_NumIn[79:72]; // @[sub_module.scala 32:32]
wire [7:0] temp_10 = io_NumIn[87:80]; // @[sub_module.scala 32:32]
wire [7:0] temp_11 = io_NumIn[95:88]; // @[sub_module.scala 32:32]
wire [7:0] temp_12 = io_NumIn[103:96]; // @[sub_module.scala 32:32]
wire [7:0] temp_13 = io_NumIn[111:104]; // @[sub_module.scala 32:32]
wire [7:0] temp_14 = io_NumIn[119:112]; // @[sub_module.scala 32:32]
wire [7:0] temp_15 = io_NumIn[127:120]; // @[sub_module.scala 32:32]
wire [63:0] lo = {temp_8,temp_9,temp_10,temp_11,temp_12,temp_13,temp_14,temp_15}; // @[sub_module.scala 35:28]
wire [63:0] hi = {temp_0,temp_1,temp_2,temp_3,temp_4,temp_5,temp_6,temp_7}; // @[sub_module.scala 35:28]
assign io_NumOut = {hi,lo}; // @[sub_module.scala 35:28]
endmodule
功能确实是对的,如何去除这些烦人的注释呢?写了一个脚本remove.py,还挺好用
# python3 remove.py -f yourfile.v
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-f','--file',dest='file',type=str,default='yourfile.v')
args = parser.parse_args()
file_data = ""
remove = 0
with open(args.file,"r",encoding="utf-8") as f:
for line in f:
if(line[1:3]=="if" or line[0:7]=="initial"):
remove += 1
temp = ""
elif(line[1:4]=="end" or line[0:6]=="end //"):
remove -= 1
temp = ""
else:
if(remove!=0):
temp=""
else:
temp = line.split('/')[0]
if((len(temp)!=0) and (temp[-1]!='\n')) :
temp += '\n'
file_data += temp
with open(args.file,"w",encoding= "utf-8") as f:
f.write(file_data)
处理之后瞬间清爽了:
module EndianCnvt(
input clock,
input reset,
input [127:0] io_NumIn,
output [127:0] io_NumOut
);
wire [7:0] temp_0 = io_NumIn[7:0];
wire [7:0] temp_1 = io_NumIn[15:8];
wire [7:0] temp_2 = io_NumIn[23:16];
wire [7:0] temp_3 = io_NumIn[31:24];
wire [7:0] temp_4 = io_NumIn[39:32];
wire [7:0] temp_5 = io_NumIn[47:40];
wire [7:0] temp_6 = io_NumIn[55:48];
wire [7:0] temp_7 = io_NumIn[63:56];
wire [7:0] temp_8 = io_NumIn[71:64];
wire [7:0] temp_9 = io_NumIn[79:72];
wire [7:0] temp_10 = io_NumIn[87:80];
wire [7:0] temp_11 = io_NumIn[95:88];
wire [7:0] temp_12 = io_NumIn[103:96];
wire [7:0] temp_13 = io_NumIn[111:104];
wire [7:0] temp_14 = io_NumIn[119:112];
wire [7:0] temp_15 = io_NumIn[127:120];
wire [63:0] lo = {temp_8,temp_9,temp_10,temp_11,temp_12,temp_13,temp_14,temp_15};
wire [63:0] hi = {temp_0,temp_1,temp_2,temp_3,temp_4,temp_5,temp_6,temp_7};
assign io_NumOut = {hi,lo};
endmodule
附上寄存器、向量初始化的语句备忘
val regs = RegInit(VecInit(Seq.fill(32)(0.U(32.W))))//寄存器向量初始化
val reg = RegNext(updateData,resetData,enable)
val reg2 = ShiftRegister(in , n , en )
val reg3 = ShiftRegister(in ,n ,resetData,en)
val reg4 = Reg(Vec(32,SInt(64.W)))
val array = Wire(Vec(4,SInt(8.W)))
val array1 = array.asTypeOf(Vec(2,UInt(16.W)))
val array2 = VecInit(Seq.fill(4)(false.B))
val array3 = VecInit(Seq.fill(4)(0.S))
//rom
val mem = VecInit("h11".U,"hff".U,"h15".U,"h31".U)