csd/
csd_multiplier.rs

1use std::fmt::Write;
2
3#[derive(Debug)]
4pub enum CsdMultiplierError {
5    InvalidCharacter,
6    LengthMismatch,
7}
8
9pub struct CsdMultiplier {
10    csd: String,
11    n: usize,
12    m: usize,
13}
14
15impl CsdMultiplier {
16    pub fn new(csd: &str, n: usize, m: usize) -> Result<Self, CsdMultiplierError> {
17        // Validate CSD string
18        if !csd.chars().all(|c| matches!(c, '+' | '-' | '0')) {
19            return Err(CsdMultiplierError::InvalidCharacter);
20        }
21
22        // Validate length matches M
23        if csd.len() != m + 1 {
24            return Err(CsdMultiplierError::LengthMismatch);
25        }
26
27        Ok(Self {
28            csd: csd.to_string(),
29            n,
30            m,
31        })
32    }
33
34    /// Calculate the decimal value represented by the CSD string
35    fn decimal_value(&self) -> i32 {
36        self.csd.chars().fold(0, |acc, c| {
37            let acc = acc << 1;
38            match c {
39                '+' => acc + 1,
40                '-' => acc - 1,
41                '0' => acc,
42                _ => unreachable!(),
43            }
44        })
45    }
46
47    /// Generate the Verilog module code
48    pub fn generate_verilog(&self) -> String {
49        let mut output = String::new();
50        self.generate_header(&mut output);
51        self.generate_wires(&mut output);
52        self.generate_result(&mut output);
53        writeln!(output, "endmodule").unwrap();
54        output
55    }
56
57    fn generate_header(&self, output: &mut String) {
58        writeln!(
59            output,
60            "// CSD Multiplier for pattern: {} (value: {})",
61            self.csd,
62            self.decimal_value()
63        )
64        .unwrap();
65
66        writeln!(
67            output,
68            "module csd_multiplier (
69    input signed [{}:0] x,      // Input value (signed)
70    output signed [{}:0] result // Result (signed)
71);",
72            self.n - 1,
73            self.n + self.m - 1
74        )
75        .unwrap();
76    }
77
78    fn get_terms(&self) -> Vec<(usize, char)> {
79        self.csd
80            .chars()
81            .enumerate()
82            .filter_map(|(i, c)| {
83                let power = self.m - i;
84                match c {
85                    '+' => Some((power, '+')),
86                    '-' => Some((power, '-')),
87                    '0' => None,
88                    _ => unreachable!(),
89                }
90            })
91            .collect()
92    }
93
94    fn generate_wires(&self, output: &mut String) {
95        let terms = self.get_terms();
96        if terms.is_empty() {
97            return;
98        }
99
100        let shift_powers: Vec<_> = {
101            let mut powers: Vec<_> = terms.iter().map(|(p, _)| *p).collect();
102            powers.sort_by(|a, b| b.cmp(a)); // Sort descending
103            powers.dedup();
104            powers
105        };
106
107        writeln!(
108            output,
109            "\n    // Signed shifted versions (Verilog handles sign extension)"
110        )
111        .unwrap();
112
113        for &power in &shift_powers {
114            let padding = self.m - power;
115            writeln!(
116                output,
117                "    wire signed [{}:0] x_shift{} = $signed({{ {{{}{{x[{}]}}}}, x}}) << {};",
118                self.n + self.m - 1,
119                power,
120                padding,
121                self.n - 1,
122                power
123            )
124            .unwrap();
125        }
126    }
127
128    fn generate_result(&self, output: &mut String) {
129        writeln!(output, "\n    // CSD implementation with signed arithmetic").unwrap();
130        let terms = self.get_terms();
131
132        if terms.is_empty() {
133            writeln!(output, "    assign result = 0;").unwrap();
134        } else {
135            let (first_power, first_op) = terms[0];
136            let mut expr = format!("{}x_shift{}", first_op, first_power);
137
138            for (power, op) in &terms[1..] {
139                expr.push_str(&format!(" {} x_shift{}", op, power));
140            }
141
142            writeln!(output, "    assign result = {};", expr.replace("+", "")).unwrap();
143        }
144    }
145}
146
147// fn main() {
148//     let csd = "+00-00+"; // Represents 57
149//     let n = 8; // Input bit width
150//     let m = 6; // Highest power (2^6 for this CSD)
151
152//     let multiplier = CsdMultiplier::new(csd, n, m).expect("Invalid CSD parameters");
153
154//     println!("{}", multiplier.generate_verilog());
155// }
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_valid_csd() {
163        let csd = "+00-00+0+";
164        let multiplier = CsdMultiplier::new(csd, 8, 8).unwrap();
165        assert_eq!(multiplier.decimal_value(), 229);
166    }
167
168    #[test]
169    fn test_invalid_csd_chars() {
170        let csd = "+01-00+0+";
171        let result = CsdMultiplier::new(csd, 8, 6);
172        assert!(matches!(result, Err(CsdMultiplierError::InvalidCharacter)));
173    }
174
175    #[test]
176    fn test_length_mismatch() {
177        let csd = "+00-00+0+";
178        let result = CsdMultiplier::new(csd, 8, 5);
179        assert!(matches!(result, Err(CsdMultiplierError::LengthMismatch)));
180    }
181
182    #[test]
183    fn test_verilog_generation() {
184        let csd = "+0-";
185        let n = 8;
186        let m = 2;
187        let multiplier = CsdMultiplier::new(csd, n, m).unwrap();
188        let expected_verilog = r###"// CSD Multiplier for pattern: +0- (value: 3)
189module csd_multiplier (
190    input signed [7:0] x,      // Input value (signed)
191    output signed [9:0] result // Result (signed)
192);
193
194    // Signed shifted versions (Verilog handles sign extension)
195    wire signed [9:0] x_shift2 = $signed({ {0{x[7]}}, x}) << 2;
196    wire signed [9:0] x_shift0 = $signed({ {2{x[7]}}, x}) << 0;
197
198    // CSD implementation with signed arithmetic
199    assign result = x_shift2 - x_shift0;
200endmodule
201"###;
202        assert_eq!(multiplier.generate_verilog(), expected_verilog);
203    }
204}