-
Notifications
You must be signed in to change notification settings - Fork 19
CRC Generation Module #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 22 commits
bf62871
6a36944
472b6da
78584bc
d27e94b
d2ab201
7341b9f
643b383
2b9bb8a
a0ed001
ad22060
eaead7e
ba286e3
6ee2f2b
63cd816
7a8e649
0b3c701
618df0b
252ed7e
b2837fd
966ba5e
5465b45
2bf4ecb
7f83684
8946b69
d6d3b53
97a8bb0
cbeb474
091cddf
3d4ee4f
1df3eda
71d1365
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,271 @@ | ||
| package edu.berkeley.cs.ucie.digital.d2dadapter | ||
|
|
||
| import chisel3._ | ||
|
|
||
| class CRC16Lookup { | ||
|
|
||
| /** Lookup table for CRC-16 (0x8005) polynomial. Consumes message from MSB | ||
| * Byte to LSB Byte and results in CRC[15:0] in unreversed format as detailed | ||
| * in UCIe1.1 spec. | ||
| */ | ||
|
|
||
| val table = VecInit( | ||
| 0x0000.U, | ||
| 0x8005.U, | ||
| 0x800f.U, | ||
| 0x000a.U, | ||
| 0x801b.U, | ||
| 0x001e.U, | ||
| 0x0014.U, | ||
| 0x8011.U, | ||
| 0x8033.U, | ||
| 0x0036.U, | ||
| 0x003c.U, | ||
| 0x8039.U, | ||
| 0x0028.U, | ||
| 0x802d.U, | ||
| 0x8027.U, | ||
| 0x0022.U, | ||
| 0x8063.U, | ||
| 0x0066.U, | ||
| 0x006c.U, | ||
| 0x8069.U, | ||
| 0x0078.U, | ||
| 0x807d.U, | ||
| 0x8077.U, | ||
| 0x0072.U, | ||
| 0x0050.U, | ||
| 0x8055.U, | ||
| 0x805f.U, | ||
| 0x005a.U, | ||
| 0x804b.U, | ||
| 0x004e.U, | ||
| 0x0044.U, | ||
| 0x8041.U, | ||
| 0x80c3.U, | ||
| 0x00c6.U, | ||
| 0x00cc.U, | ||
| 0x80c9.U, | ||
| 0x00d8.U, | ||
| 0x80dd.U, | ||
| 0x80d7.U, | ||
| 0x00d2.U, | ||
| 0x00f0.U, | ||
| 0x80f5.U, | ||
| 0x80ff.U, | ||
| 0x00fa.U, | ||
| 0x80eb.U, | ||
| 0x00ee.U, | ||
| 0x00e4.U, | ||
| 0x80e1.U, | ||
| 0x00a0.U, | ||
| 0x80a5.U, | ||
| 0x80af.U, | ||
| 0x00aa.U, | ||
| 0x80bb.U, | ||
| 0x00be.U, | ||
| 0x00b4.U, | ||
| 0x80b1.U, | ||
| 0x8093.U, | ||
| 0x0096.U, | ||
| 0x009c.U, | ||
| 0x8099.U, | ||
| 0x0088.U, | ||
| 0x808d.U, | ||
| 0x8087.U, | ||
| 0x0082.U, | ||
| 0x8183.U, | ||
| 0x0186.U, | ||
| 0x018c.U, | ||
| 0x8189.U, | ||
| 0x0198.U, | ||
| 0x819d.U, | ||
| 0x8197.U, | ||
| 0x0192.U, | ||
| 0x01b0.U, | ||
| 0x81b5.U, | ||
| 0x81bf.U, | ||
| 0x01ba.U, | ||
| 0x81ab.U, | ||
| 0x01ae.U, | ||
| 0x01a4.U, | ||
| 0x81a1.U, | ||
| 0x01e0.U, | ||
| 0x81e5.U, | ||
| 0x81ef.U, | ||
| 0x01ea.U, | ||
| 0x81fb.U, | ||
| 0x01fe.U, | ||
| 0x01f4.U, | ||
| 0x81f1.U, | ||
| 0x81d3.U, | ||
| 0x01d6.U, | ||
| 0x01dc.U, | ||
| 0x81d9.U, | ||
| 0x01c8.U, | ||
| 0x81cd.U, | ||
| 0x81c7.U, | ||
| 0x01c2.U, | ||
| 0x0140.U, | ||
| 0x8145.U, | ||
| 0x814f.U, | ||
| 0x014a.U, | ||
| 0x815b.U, | ||
| 0x015e.U, | ||
| 0x0154.U, | ||
| 0x8151.U, | ||
| 0x8173.U, | ||
| 0x0176.U, | ||
| 0x017c.U, | ||
| 0x8179.U, | ||
| 0x0168.U, | ||
| 0x816d.U, | ||
| 0x8167.U, | ||
| 0x0162.U, | ||
| 0x8123.U, | ||
| 0x0126.U, | ||
| 0x012c.U, | ||
| 0x8129.U, | ||
| 0x0138.U, | ||
| 0x813d.U, | ||
| 0x8137.U, | ||
| 0x0132.U, | ||
| 0x0110.U, | ||
| 0x8115.U, | ||
| 0x811f.U, | ||
| 0x011a.U, | ||
| 0x810b.U, | ||
| 0x010e.U, | ||
| 0x0104.U, | ||
| 0x8101.U, | ||
| 0x8303.U, | ||
| 0x0306.U, | ||
| 0x030c.U, | ||
| 0x8309.U, | ||
| 0x0318.U, | ||
| 0x831d.U, | ||
| 0x8317.U, | ||
| 0x0312.U, | ||
| 0x0330.U, | ||
| 0x8335.U, | ||
| 0x833f.U, | ||
| 0x033a.U, | ||
| 0x832b.U, | ||
| 0x032e.U, | ||
| 0x0324.U, | ||
| 0x8321.U, | ||
| 0x0360.U, | ||
| 0x8365.U, | ||
| 0x836f.U, | ||
| 0x036a.U, | ||
| 0x837b.U, | ||
| 0x037e.U, | ||
| 0x0374.U, | ||
| 0x8371.U, | ||
| 0x8353.U, | ||
| 0x0356.U, | ||
| 0x035c.U, | ||
| 0x8359.U, | ||
| 0x0348.U, | ||
| 0x834d.U, | ||
| 0x8347.U, | ||
| 0x0342.U, | ||
| 0x03c0.U, | ||
| 0x83c5.U, | ||
| 0x83cf.U, | ||
| 0x03ca.U, | ||
| 0x83db.U, | ||
| 0x03de.U, | ||
| 0x03d4.U, | ||
| 0x83d1.U, | ||
| 0x83f3.U, | ||
| 0x03f6.U, | ||
| 0x03fc.U, | ||
| 0x83f9.U, | ||
| 0x03e8.U, | ||
| 0x83ed.U, | ||
| 0x83e7.U, | ||
| 0x03e2.U, | ||
| 0x83a3.U, | ||
| 0x03a6.U, | ||
| 0x03ac.U, | ||
| 0x83a9.U, | ||
| 0x03b8.U, | ||
| 0x83bd.U, | ||
| 0x83b7.U, | ||
| 0x03b2.U, | ||
| 0x0390.U, | ||
| 0x8395.U, | ||
| 0x839f.U, | ||
| 0x039a.U, | ||
| 0x838b.U, | ||
| 0x038e.U, | ||
| 0x0384.U, | ||
| 0x8381.U, | ||
| 0x0280.U, | ||
| 0x8285.U, | ||
| 0x828f.U, | ||
| 0x028a.U, | ||
| 0x829b.U, | ||
| 0x029e.U, | ||
| 0x0294.U, | ||
| 0x8291.U, | ||
| 0x82b3.U, | ||
| 0x02b6.U, | ||
| 0x02bc.U, | ||
| 0x82b9.U, | ||
| 0x02a8.U, | ||
| 0x82ad.U, | ||
| 0x82a7.U, | ||
| 0x02a2.U, | ||
| 0x82e3.U, | ||
| 0x02e6.U, | ||
| 0x02ec.U, | ||
| 0x82e9.U, | ||
| 0x02f8.U, | ||
| 0x82fd.U, | ||
| 0x82f7.U, | ||
| 0x02f2.U, | ||
| 0x02d0.U, | ||
| 0x82d5.U, | ||
| 0x82df.U, | ||
| 0x02da.U, | ||
| 0x82cb.U, | ||
| 0x02ce.U, | ||
| 0x02c4.U, | ||
| 0x82c1.U, | ||
| 0x8243.U, | ||
| 0x0246.U, | ||
| 0x024c.U, | ||
| 0x8249.U, | ||
| 0x0258.U, | ||
| 0x825d.U, | ||
| 0x8257.U, | ||
| 0x0252.U, | ||
| 0x0270.U, | ||
| 0x8275.U, | ||
| 0x827f.U, | ||
| 0x027a.U, | ||
| 0x826b.U, | ||
| 0x026e.U, | ||
| 0x0264.U, | ||
| 0x8261.U, | ||
| 0x0220.U, | ||
| 0x8225.U, | ||
| 0x822f.U, | ||
| 0x022a.U, | ||
| 0x823b.U, | ||
| 0x023e.U, | ||
| 0x0234.U, | ||
| 0x8231.U, | ||
| 0x8213.U, | ||
| 0x0216.U, | ||
| 0x021c.U, | ||
| 0x8219.U, | ||
| 0x0208.U, | ||
| 0x820d.U, | ||
| 0x8207.U, | ||
| 0x0202.U, | ||
| ) | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| package edu.berkeley.cs.ucie.digital.d2dadapter | ||
|
|
||
| import chisel3._ | ||
| import chisel3.util._ | ||
|
|
||
| /** Generates the CRC of data using the polynomial x^16 + x^15 + x^2 + 1. The | ||
| * message must be formatted according to the UCIe1.1 spec, and the message | ||
| * will be consumed one byte per clock cycle, starting from the MSB to the LSB. | ||
| * The calculated 2 byte CRC will be available on the crc ReadyValid3IO | ||
| * interface in the raw, un-reversed format as indicated in the UCIe1.1 spec | ||
| * (i.e. CRC[15] is the MSB of the crc interface's data bits). | ||
| * @param width | ||
| * The message size in bits (must be whole number of bytes). UCIe1.1 spec | ||
| * will use 1024-bit messages, with shorter messages padded with 0s in MSB | ||
| * side. | ||
| * @groupdesc Signals | ||
| * The input and output controls of the CRCGenerator module | ||
| */ | ||
|
|
||
| class CRCGenerator(width: Int) extends Module { | ||
| assert(width % 8 == 0) | ||
| val io = IO(new Bundle { | ||
|
|
||
| /** ReadyValidIO interface to allow consumer to transfer message bits to the | ||
| * CRCGenerator. Message bits are latched when message ready and message | ||
| * valid are high for the same clock cycle, and then the CRCGenerator is | ||
| * locked into the calculation loop. | ||
| * | ||
| * The CRCGenerator will not accept new messages during the calculation | ||
| * loop, nor reflect any changes that occur to the message data bits after | ||
| * the message was latched on the ready/valid transfer. | ||
| * | ||
| * The CRCGenerator will only accept a new message after the CRC data has | ||
| * been transfered through the CRC ReadyValid3IO interface. | ||
| * @group Signals | ||
| */ | ||
| val message = Flipped(Decoupled(Bits(width.W))) | ||
|
|
||
| /** ReadyValidIO interface to allow CRCGenerator to transfer crc bits to the | ||
| * consumer. CRC will be cleared to 0 and invalid on reset. | ||
| * | ||
| * Once message bits have been transfered, the CRCGenerator will enter the | ||
| * calculation loop, consuming the message data one byte each clock cycle | ||
| * until all bytes have been consumed. The CRC data bits on the interface | ||
| * willl then become valid with the crc valid signal set high. | ||
| * | ||
| * The CRC data will remain valid and the CRCGenerator will remain in an | ||
| * idle state until the consumer initiates a transfer of the CRC data by | ||
| * signaling CRC ready high. After this transfer, the CRC data will become | ||
| * invalid and the CRC Generator will signal message ready to accept a new | ||
| * message. | ||
| * @group Signals | ||
| */ | ||
| val crc = Decoupled(Bits(16.W)) | ||
| }) | ||
|
|
||
| // Output data registers | ||
| val crc0 = RegInit(Bits(8.W), 0.U) | ||
| val crc1 = RegInit(Bits(8.W), 0.U) | ||
|
|
||
| // Output signal registers | ||
| val message_ready = RegInit(Bool(), true.B) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: camelcase?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I was told to use snake case by @rahulk29, but I can switch it to camelcase if that is recommended. |
||
| val crc_valid = RegInit(Bool(), false.B) | ||
|
|
||
| // CRC calculating registers | ||
| // Store number of bytes in width bits | ||
| val step = RegInit(0.U(log2Ceil(width / 8 + 1).W)) | ||
| // Latches full message when message_ready and data_val | ||
| val message_bits = RegInit(Bits(width.W), 0.U) | ||
|
|
||
| // CRC calculating table | ||
| val lookup = new CRC16Lookup | ||
|
|
||
| // Propogate output data register | ||
| io.crc.bits := Cat(crc1, crc0) | ||
|
|
||
| // Propogate crc valid and message ready signal | ||
| io.crc.valid := crc_valid | ||
| io.message.ready := message_ready | ||
|
|
||
| // Latch data on message_ready and data_val | ||
| when(io.message.fire) { | ||
| // Reset logic | ||
| crc0 := 0.U | ||
| crc1 := 0.U | ||
| crc_valid := false.B | ||
|
|
||
| step := (width / 8).U // Set step to number of bytes in word | ||
| message_bits := io.message.bits | ||
| message_ready := false.B | ||
| } | ||
|
|
||
| // Computation not finished when step is not 0 | ||
| when(step > 0.U) { | ||
| crc1 := crc0 ^ lookup | ||
| .table(crc1 ^ message_bits(width - 1, width - 8))(15, 8) | ||
| crc0 := lookup.table(crc1 ^ message_bits(width - 1, width - 8))(7, 0) | ||
| message_bits := message_bits << 8 | ||
|
||
| step := step - 1.U | ||
| crc_valid := step === 1.U // If next step will be 0, CRC is now valid | ||
| } | ||
|
|
||
| /* Idle with crc output valid until consumer initiates transfer of CRC with | ||
| * io.crc.ready */ | ||
| when(io.crc.fire) { | ||
| crc_valid := false.B | ||
| message_ready := true.B | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.